﻿
// MIT License

// Copyright (c) 2020 Tsukanov Alexander

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#Область Константы

Перем КлючевыеСлова;             // перечисление
Перем Токены;                    // перечисление
Перем Типы;                      // перечисление
Перем Директивы;                 // перечисление
Перем Аннотации;                 // перечисление
Перем ИнструкцииПрепроцессора;   // перечисление
Перем СимволыПрепроцессора;      // перечисление
Перем Ошибки;                    // массив (строка)
Перем ЛитералКромеСтроки;        // массив (один из Токены)
Перем ОперацииСравнения;         // массив (один из Токены)
Перем ОперацииАддитивные;        // массив (один из Токены)
Перем ОперацииМультипликативные; // массив (один из Токены)
Перем ТокеныНачалаВыражения;     // массив (один из Токены)
Перем ПустойМассив;              // массив
Перем КартаТокенов;              // соответствие[строка] (строка)
Перем КартаБуквЦифр;             // соответствие[строка] (строка)
Перем Буква, Цифра;              // строка
Перем Символы_ПС;                // строка

#КонецОбласти // Константы

#Область Параметры

Перем СтрогийРежим Экспорт;

#КонецОбласти // Параметры

#Область СостояниеПарсера

Перем Парсер_Исходник;                // строка
Перем Парсер_ДлинаИсходника;          // число
Перем Парсер_НомерТекущейСтроки;      // число
Перем Парсер_ТекущаяПозиция;          // число
Перем Парсер_ПозицияНачалаТокена;     // число
Перем Парсер_Символ;                  // строка
Перем Парсер_Токен;                   // строка (один из Токены)
Перем Парсер_Литерал;                 // строка
Перем Парсер_Значение;                // число, строка, дата, булево, неопределено, null
Перем Парсер_Окружение;               // структура (Окружение)
Перем Парсер_Переменные;              // структура как соответствие[строка] (ЭлементОкружения)
Перем Парсер_Методы;                  // структура как соответствие[строка] (ЭлементОкружения)
Перем Парсер_Неизвестные;             // структура как соответствие[строка] (ЭлементОкружения)
Перем Парсер_ТочкиВызова;             // соответствие[ЭлементОкружения] (число)
Перем Парсер_ЭтоФункция;              // булево
Перем Парсер_ПеременныеРазрешены;     // булево
Перем Парсер_СписокДиректив;          // массив (ОбъявлениеДирективы)
Перем Парсер_СписокАннотаций;         // массив (ОбъявлениеАннотации)
Перем Парсер_Интерфейс;               // массив (ЭлементОкружения)
Перем Парсер_Ошибки;                  // таблица
Перем Парсер_Замены;                  // таблица
Перем Парсер_Токены;                  // таблица
Перем Парсер_ПозицияТекущейСтроки;    // число
Перем Парсер_ИндексТокена;            // число
Перем Парсер_ДанныеТекущегоТокена;    // один из ТаблицаТокенов
Перем Парсер_ДанныеПредыдущегоТокена; // один из ТаблицаТокенов
Перем Парсер_Узлы;                    // структура как соответствие[строка] (таблица значений)
Перем Парсер_ЭтоАсинх;                // булево

#КонецОбласти // СостояниеПарсера

#Область СостояниеПосетителя

Перем Посетитель_Плагины;  // массив (Обработка)
Перем Посетитель_Подписки; // структура как соответствие[строка] (массив)
Перем Посетитель_Стек;     // структура
Перем Посетитель_Счетчики; // структура как соответствие[строка] (число)

#КонецОбласти // СостояниеПосетителя

#Область Инициализация

Процедура Инициализировать()
	Перем Буквы, Индекс, Символ;
	
	ИнициализироватьПеречисления();
	ИнициализироватьУзлы();
	
	ЛитералКромеСтроки = Новый Массив;
	ЛитералКромеСтроки.Добавить(Токены.Число);
	ЛитералКромеСтроки.Добавить(Токены.ДатаВремя);
	ЛитералКромеСтроки.Добавить(Токены.Истина);
	ЛитералКромеСтроки.Добавить(Токены.Ложь);
	ЛитералКромеСтроки.Добавить(Токены.Неопределено);
	ЛитералКромеСтроки.Добавить(Токены.Null);
	
	ОперацииСравнения = Новый Массив;
	ОперацииСравнения.Добавить(Токены.ЗнакРавно);
	ОперацииСравнения.Добавить(Токены.ЗнакНеРавно);
	ОперацииСравнения.Добавить(Токены.ЗнакМеньше);
	ОперацииСравнения.Добавить(Токены.ЗнакБольше);
	ОперацииСравнения.Добавить(Токены.ЗнакМеньшеИлиРавно);
	ОперацииСравнения.Добавить(Токены.ЗнакБольшеИлиРавно);
	
	ОперацииАддитивные = Новый Массив;
	ОперацииАддитивные.Добавить(Токены.ЗнакСложения);
	ОперацииАддитивные.Добавить(Токены.ЗнакВычитания);
	
	ОперацииМультипликативные = Новый Массив;
	ОперацииМультипликативные.Добавить(Токены.ЗнакУмножения);
	ОперацииМультипликативные.Добавить(Токены.ЗнакДеления);
	ОперацииМультипликативные.Добавить(Токены.ЗнакОстатка);
	
	ТокеныНачалаВыражения = Новый Массив;
	ТокеныНачалаВыражения.Добавить(Токены.ЗнакСложения);
	ТокеныНачалаВыражения.Добавить(Токены.ЗнакВычитания);
	ТокеныНачалаВыражения.Добавить(Токены.Не);
	ТокеныНачалаВыражения.Добавить(Токены.Идентификатор);
	ТокеныНачалаВыражения.Добавить(Токены.ЛеваяКруглаяСкобка);
	ТокеныНачалаВыражения.Добавить(Токены.Число);
	ТокеныНачалаВыражения.Добавить(Токены.Строка);
	ТокеныНачалаВыражения.Добавить(Токены.НачалоСтроки);
	ТокеныНачалаВыражения.Добавить(Токены.ДатаВремя);
	ТокеныНачалаВыражения.Добавить(Токены.ЗнакВопроса);
	ТокеныНачалаВыражения.Добавить(Токены.Новый);
	ТокеныНачалаВыражения.Добавить(Токены.Истина);
	ТокеныНачалаВыражения.Добавить(Токены.Ложь);
	ТокеныНачалаВыражения.Добавить(Токены.Неопределено);
	ТокеныНачалаВыражения.Добавить(Токены.Null);
	ТокеныНачалаВыражения.Добавить(Токены.Ждать);
	
	ПустойМассив = Новый Массив;
	
	Символы_ПС = Символы.ПС;
	
	Буква = "Буква";
	Цифра = "Цифра";
	
	КартаТокенов = Новый Соответствие;
	КартаБуквЦифр = Новый Соответствие;
	
	Буквы = (
	"abcdefghijklmnopqrstuvwxyz"
	+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	+ "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"
	+ "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"
);
Индекс = 1;
Символ = "_";
Пока Символ <> "" Цикл
	КартаТокенов[Символ] = Буква;
	КартаБуквЦифр[Символ] = Буква;
	Символ = Сред(Буквы, Индекс, 1);
	Индекс = Индекс + 1;
КонецЦикла;

Для Индекс = 0 По 9 Цикл
	КартаТокенов[Строка(Индекс)] = Цифра;
	КартаБуквЦифр[Строка(Индекс)] = Цифра;
КонецЦикла;

КартаТокенов[""""] = Токены.НачалоСтроки;
КартаТокенов["|"] = Токены.ПродолжениеСтроки;
КартаТокенов["'"] = Токены.ДатаВремя;
КартаТокенов["="] = Токены.ЗнакРавно;
КартаТокенов["+"] = Токены.ЗнакСложения;
КартаТокенов["-"] = Токены.ЗнакВычитания;
КартаТокенов["*"] = Токены.ЗнакУмножения;
КартаТокенов["%"] = Токены.ЗнакОстатка;
КартаТокенов["("] = Токены.ЛеваяКруглаяСкобка;
КартаТокенов[")"] = Токены.ПраваяКруглаяСкобка;
КартаТокенов["["] = Токены.ЛеваяКвадратнаяСкобка;
КартаТокенов["]"] = Токены.ПраваяКвадратнаяСкобка;
КартаТокенов["?"] = Токены.ЗнакВопроса;
КартаТокенов[","] = Токены.Запятая;
КартаТокенов["."] = Токены.Точка;
КартаТокенов[":"] = Токены.Двоеточие;
КартаТокенов[";"] = Токены.ТочкаСЗапятой;
КартаТокенов[""] = Токены.КонецТекста;

Ошибки = Новый Массив(22);
Ошибки[00] = Неопределено; // ошибки регистрируемые плагинами
Ошибки[01] = "Ожидалось";
Ошибки[02] = "Ожидалась директива";
Ошибки[03] = "Неизвестная директива";
Ошибки[04] = "Ожидалась инструкция препроцессора";
Ошибки[05] = "Неизвестная инструкция препроцессора";
Ошибки[06] = "Не обнаружено объявление метода";
Ошибки[07] = "Ожидался операнд";
Ошибки[08] = "Ожидался конструктор";
Ошибки[09] = "Ожидалось не более двух аргументов";
Ошибки[10] = "Не обнаружено объявление идентификатора";
Ошибки[11] = "Ожидалось выражение";
Ошибки[12] = "Повторное объявление идентификатора";
Ошибки[13] = "Повторное объявление метода";
Ошибки[14] = "Ожидалась переменная";
Ошибки[15] = "Имя события указано неправильно";
Ошибки[16] = "Имя метода указано неправильно";
Ошибки[17] = "Ожидался символ препроцессора";
Ошибки[18] = "Ошибка в литерале даты";
Ошибки[19] = "Не удалось выполнить замену";
Ошибки[20] = "Ожидалось имя или путь";
Ошибки[21] = "Оператор Ждать (Await) может употребляться только в асинхронных процедурах или функциях";

СтрогийРежим = Ложь;

Парсер_Ошибки = Новый ТаблицаЗначений;
// основные поля
Парсер_Ошибки.Колонки.Добавить("Источник", Новый ОписаниеТипов("Строка"));
Парсер_Ошибки.Колонки.Добавить("Код", Новый ОписаниеТипов("Число"));
Парсер_Ошибки.Колонки.Добавить("Текст", Новый ОписаниеТипов("Строка"));
Парсер_Ошибки.Колонки.Добавить("ПозицияНачала", Новый ОписаниеТипов("Число"));
Парсер_Ошибки.Колонки.Добавить("НомерСтрокиНачала", Новый ОписаниеТипов("Число"));
Парсер_Ошибки.Колонки.Добавить("НомерКолонкиНачала", Новый ОписаниеТипов("Число"));
Парсер_Ошибки.Колонки.Добавить("ПозицияКонца", Новый ОписаниеТипов("Число"));
Парсер_Ошибки.Колонки.Добавить("НомерСтрокиКонца", Новый ОписаниеТипов("Число"));
Парсер_Ошибки.Колонки.Добавить("НомерКолонкиКонца", Новый ОписаниеТипов("Число"));
Парсер_Ошибки.Колонки.Добавить("ЕстьЗамена", Новый ОписаниеТипов("Булево"));
// дополнительные поля
Парсер_Ошибки.Колонки.Добавить("МинутНаИсправление", Новый ОписаниеТипов("Число"));
Парсер_Ошибки.Колонки.Добавить("Серьезность", Новый ОписаниеТипов("Строка"));
Парсер_Ошибки.Колонки.Добавить("Приоритет", Новый ОписаниеТипов("Число"));
Парсер_Ошибки.Колонки.Добавить("Правило", Новый ОписаниеТипов("Строка"));
Парсер_Ошибки.Колонки.Добавить("Тип", Новый ОписаниеТипов("Строка"));

Парсер_Токены = Новый ТаблицаЗначений;
Парсер_Токены.Колонки.Добавить("Индекс", Новый ОписаниеТипов("Число"));
Парсер_Токены.Колонки.Добавить("Токен", Новый ОписаниеТипов("Строка"));
Парсер_Токены.Колонки.Добавить("НомерСтроки", Новый ОписаниеТипов("Число"));
Парсер_Токены.Колонки.Добавить("НомерКолонки", Новый ОписаниеТипов("Число"));
Парсер_Токены.Колонки.Добавить("Позиция", Новый ОписаниеТипов("Число"));
Парсер_Токены.Колонки.Добавить("Длина", Новый ОписаниеТипов("Число"));

Парсер_Замены = Новый ТаблицаЗначений;
Парсер_Замены.Колонки.Добавить("Источник", Новый ОписаниеТипов("Строка"));
Парсер_Замены.Колонки.Добавить("Текст", Новый ОписаниеТипов("Строка"));
Парсер_Замены.Колонки.Добавить("Позиция", Новый ОписаниеТипов("Число"));
Парсер_Замены.Колонки.Добавить("Длина", Новый ОписаниеТипов("Число"));

КонецПроцедуры // Инициализировать()

Процедура ИнициализироватьПеречисления()
	КлючевыеСлова = КлючевыеСлова();
	Токены = Токены(КлючевыеСлова);
	Типы = Типы();
	Директивы = Директивы();
	Аннотации = Аннотации();
	ИнструкцииПрепроцессора = ИнструкцииПрепроцессора();
	СимволыПрепроцессора = СимволыПрепроцессора();
КонецПроцедуры // ИнициализироватьПеречисления()

Процедура ИнициализироватьУзлы()
	
	Парсер_Узлы = Новый Структура;
	
	Парсер_Узлы.Вставить("Модуль", Новый ТаблицаЗначений);
	// Корень AST. Узел хранит информацию о модуле в целом.
	Поля = Парсер_Узлы.Модуль.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Объявления"); // массив (один из #Объявления)
	Поля.Добавить("Переменные"); // массив (ОбъявлениеПеременнойМодуля, ОбъявлениеАвтоПеременной)
	Поля.Добавить("Операторы"); // массив (один из #Операторы)
	Поля.Добавить("Интерфейс"); // массив (ЭлементОкружения)
	
	Парсер_Узлы.Вставить("ЭлементОкружения", Новый ТаблицаЗначений);
	// Узел хранит информацию об объекте области видимости.
	// Поле Объявление хранит объявление данного объекта (неопределено = объявление не обнаружено).
	Поля = Парсер_Узлы.ЭлементОкружения.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Имя"); // строка
	Поля.Добавить("Объявление"); // неопределено, структура (один из #Объявления)
	
	ИнициализироватьОбъявления();
	ИнициализироватьВыражения();
	ИнициализироватьОператоры();
	ИнициализироватьИнструкцииПрепроцессора();		
	ИнициализироватьВыраженияПрепроцессора();
	
КонецПроцедуры // ИнициализироватьУзлы()

Процедура ИнициализироватьОбъявления()
	
	Парсер_Узлы.Вставить("ОбъявлениеДирективы", Новый ТаблицаЗначений);
	// Хранит информацию об объявлении директивы.
	// Пример:
	// <pre>
	// &НаКлиенте
	// </pre>
	Поля = Парсер_Узлы.ОбъявлениеДирективы.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Директива"); // строка (один из Директивы)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОбъявлениеАннотации", Новый ТаблицаЗначений);
	// Хранит информацию об объявлении аннотации.
	// Пример:
	// <pre>
	// &Перед("ЗаполнитьТовары")
	// </pre>
	Поля = Парсер_Узлы.ОбъявлениеАннотации.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Аннотация"); // строка (один из Аннотации)
	Поля.Добавить("ИмяМетода"); // строка
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОбъявлениеСпискаПеременныхМодуля", Новый ТаблицаЗначений);
	// Хранит информацию об инструкции объявления переменных уровня модуля.
	// Пример:
	// <pre>
	// &НаКлиенте            // поле "Директивы"
	// Перем П1 Экспорт, П2; // поле "Объявления"
	// </pre>
	Поля = Парсер_Узлы.ОбъявлениеСпискаПеременныхМодуля.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Директивы"); // массив (ОбъявлениеДирективы)
	Поля.Добавить("Объявления"); // массив (ОбъявлениеПеременнойМодуля)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОбъявлениеПеременнойМодуля", Новый ТаблицаЗначений);
	// Хранит информацию об объявлении переменной уровня модуля.
	// Пример:
	// Объявления переменных заключены в скобки {...}
	// <pre>
	// &НаКлиенте
	// Перем {П1 Экспорт}, {П2};
	// </pre>
	Поля = Парсер_Узлы.ОбъявлениеПеременнойМодуля.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Имя"); // строка
	Поля.Добавить("Директивы"); // массив (ОбъявлениеДирективы)
	Поля.Добавить("Экспорт"); // булево
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОбъявлениеСпискаЛокальныхПеременных", Новый ТаблицаЗначений);
	// Хранит информацию об инструкции объявления переменных уровня метода.
	// Пример:
	// <pre>
	// Перем П1, П2; // поле "Объявления"
	// </pre>
	Поля = Парсер_Узлы.ОбъявлениеСпискаЛокальныхПеременных.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Объявления"); // массив (ОбъявлениеЛокальнойПеременной)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОбъявлениеЛокальнойПеременной", Новый ТаблицаЗначений);
	// Хранит информацию об объявлении локальной переменной.
	// Пример:
	// Объявления переменных заключены в скобки {...}
	// <pre>
	// Перем {П1}, {П2};
	// </pre>
	Поля = Парсер_Узлы.ОбъявлениеЛокальнойПеременной.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Имя"); // строка
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОбъявлениеАвтоПеременной", Новый ТаблицаЗначений);
	// Хранит информацию об объявлении авто-переменной.
	// Пример:
	// Объявления переменных заключены в скобки {...}
	// <pre>
	// {Макс} = 0;
	// Для {Индекс} = 0 По Массив.ВГраница() Цикл
	//	{Структура} = Массив[Индекс];
	// 	Для Каждого {Элемент} Из Структура Цикл
	//		Если Макс < Элемент.Значение Тогда
	// 			Макс = Элемент.Значение;
	// 		КонецЕсли;
	// 	КонецЦикла;
	// КонецЦикла
	// </pre>
	Поля = Парсер_Узлы.ОбъявлениеАвтоПеременной.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Имя"); // строка
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОбъявлениеПараметра", Новый ТаблицаЗначений);
	// Хранит информацию об объявлении параметра.
	// Пример:
	// Объявления параметров заключены в скобки {...}
	// <pre>
	// Процедура Тест({П1}, {Знач П2 = Неопределено})
	// </pre>
	Поля = Парсер_Узлы.ОбъявлениеПараметра.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Имя"); // строка
	Поля.Добавить("ПоЗначению"); // булево
	Поля.Добавить("Значение"); // неопределено, структура (ВыражениеУнарное, ВыражениеЛитерал)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОбъявлениеМетода", Новый ТаблицаЗначений);
	// Хранит информацию об объявлении метода.
	// Сигнатура метода хранится в поле Сигнатура.
	// Пример:
	// <pre>
	// &НаКлиенте
	// Функция Тест() Экспорт
	//     Перем П1, П2; // поле "Объявления" хранит объявления списков переменных.
	//                   // каждый элемент объявления (например П2) добавляется в поле "Переменные".
	//     П1 = 2;       // операторы собираются в поле Операторы
	//     П3 = П1 + 2;  // Авто-переменные (П2) добавляются в поле "Переменные".
	// КонецФункции
	// </pre>
	Поля = Парсер_Узлы.ОбъявлениеМетода.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Сигнатура"); // структура (ОбъявлениеСигнатурыПроцедуры, ОбъявлениеСигнатурыФункции)
	Поля.Добавить("Переменные"); // массив (ОбъявлениеЛокальнойПеременной, ОбъявлениеАвтоПеременной)
	Поля.Добавить("Объявления"); // массив (ОбъявлениеСпискаЛокальныхПеременных)
	Поля.Добавить("Операторы"); // массив (один из #Операторы)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОбъявлениеСигнатурыПроцедуры", Новый ТаблицаЗначений);
	// Хранит информацию о сигнатуре объявления процедуры.
	// Пример:
	// <pre>
	// &НаКлиенте
	// Процедура Тест(П1, П2) Экспорт
	// </pre>
	Поля = Парсер_Узлы.ОбъявлениеСигнатурыПроцедуры.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Имя"); // строка
	Поля.Добавить("Директивы"); // массив (ОбъявлениеДирективы)
	Поля.Добавить("Аннотации"); // массив (ОбъявлениеАннотации)
	Поля.Добавить("Параметры"); // массив (ОбъявлениеПараметра)
	Поля.Добавить("Экспорт"); // булево
	Поля.Добавить("Асинх"); // булево
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОбъявлениеСигнатурыФункции", Новый ТаблицаЗначений);
	// Хранит информацию о сигнатуре объявления функции.
	// Пример:
	// <pre>
	// &НаКлиенте
	// Функция Тест(П1, П2) Экспорт
	// </pre>
	Поля = Парсер_Узлы.ОбъявлениеСигнатурыФункции.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Имя"); // строка
	Поля.Добавить("Директивы"); // массив (ОбъявлениеДирективы)
	Поля.Добавить("Аннотации"); // массив (ОбъявлениеАннотации)
	Поля.Добавить("Параметры"); // массив (ОбъявлениеПараметра)
	Поля.Добавить("Экспорт"); // булево
	Поля.Добавить("Асинх"); // булево
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОбъявлениеГлобальногоОбъекта", Новый ТаблицаЗначений);
	// Хранит информацию о глобальном объекте.
	Поля = Парсер_Узлы.ОбъявлениеГлобальногоОбъекта.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Имя"); // строка
	Поля.Добавить("Доступность"); // структура (Доступность)
	
	Парсер_Узлы.Вставить("ОбъявлениеГлобальногоМетода", Новый ТаблицаЗначений);
	// Хранит информацию о глобальном методе.
	Поля = Парсер_Узлы.ОбъявлениеГлобальногоМетода.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Имя"); // строка
	Поля.Добавить("Функция"); // булево
	Поля.Добавить("Параметры"); // структура
	Поля.Добавить("Доступность"); // структура (Доступность)
	
КонецПроцедуры 

Процедура ИнициализироватьВыражения()
	
	Парсер_Узлы.Вставить("ВыражениеЛитерал", Новый ТаблицаЗначений);
	// Хранит информацию о литерале примитивного типа.
	Поля = Парсер_Узлы.ВыражениеЛитерал.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Вид"); // строка (один из Токены)
	Поля.Добавить("Значение"); // неопределено, строка, число, булево, дата, null
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ВыражениеПоле", Новый ТаблицаЗначений);
	// Хранит информацию об обращении к полю объекта через точку.
	// В поле Имя содержится имя поля.
	// В поле Аргументы содержатся аргументы вызова (если это вызов).
	// Пример:
	// <pre>
	// // обращения через точку заключены в скобки {...}
	// Значение = Объект{.Поле}
	// Значение = Объект{.Добавить(П1, П2)}
	// </pre>
	Поля = Парсер_Узлы.ВыражениеПоле.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Имя"); // строка
	Поля.Добавить("Аргументы"); // неопределено, массив (неопределено, один из #Выражения)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ВыражениеИндекс", Новый ТаблицаЗначений);
	// Хранит информацию об обращении к элементу объекта по индексу.
	// Пример:
	// <pre>
	// // обращение по индексу заключено в скобки {...}
	// Значение = Объект{[Ключ]}
	// </pre>
	Поля = Парсер_Узлы.ВыражениеИндекс.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Выражение"); // структура (один из #Выражения)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ВыражениеИдентификатор", Новый ТаблицаЗначений);
	// Хранит информацию об обращении к идентификатору.
	// В поле Голова содержится объект области видимости соответствующий идентификатору.
	// В поле Хвост содержится последовательность обращений через точку и по индексу.
	// В поле Аргументы содержатся аргументы вызова (если это вызов).
	// Пример:
	// <pre>
	// // идентификатор заключен в скобки {...}
	// // поле "Голова" будет содержать объект переменной "Запрос";
	// // поле "Хвост" будет содержать три обращения;
	// // поле "Аргументы" будет равно Неопределено, т.к. обращение к "Запрос" не является вызовом.
	// Возврат {Запрос.Выполнить().Выгрузить()[0]};
	// </pre>
	Поля = Парсер_Узлы.ВыражениеИдентификатор.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Голова"); // структура (ЭлементОкружения)
	Поля.Добавить("Хвост"); // массив (ВыражениеПоле, ВыражениеИндекс)
	Поля.Добавить("Аргументы"); // неопределено, массив (неопределено, один из #Выражения)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ВыражениеУнарное", Новый ТаблицаЗначений);
	// Хранит унарное выражение.
	// Пример:
	// <pre>
	// // унарные выражения заключены в скобки {...}
	// // поле "Операция.Токен" равно либо Токены.ЗнакСложения, либо Токены.ЗнакВычитания
	// // поле "Операнд" хранит операнд-выражение
	// Значение = {-Сумма} * 2;
	// Значение = {+Сумма};
	// Значение = {-(Сумма1 + Сумма2)} / 2;
	// </pre>
	Поля = Парсер_Узлы.ВыражениеУнарное.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Операция"); // один из ТаблицаТокенов
	Поля.Добавить("Операнд"); // структура (один из #Выражения)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ВыражениеБинарное", Новый ТаблицаЗначений);
	// Хранит бинарное выражение.
	// Пример:
	// <pre>
	// // бинарные выражения заключены в скобки {...}
	// // поле "Операция.Токен" равно одному из допустимых операторов:
	// // - логических (кроме "Не")
	// // - реляционных
	// // - арифметических
	// // поля "ЛевыйОперанд" и "ПравыйОперанд" содержат операнды-выражения
	// Если {Не Отмена И Продолжить} Тогда
	//     Значение = {Сумма1 + {Сумма2 * Коэффициент}};
	// КонецЕсли;
	// </pre>
	Поля = Парсер_Узлы.ВыражениеБинарное.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("ЛевыйОперанд"); // структура (один из #Выражения)
	Поля.Добавить("Операция"); // один из ТаблицаТокенов
	Поля.Добавить("ПравыйОперанд"); // структура (один из #Выражения)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ВыражениеНовый", Новый ТаблицаЗначений);
	// Хранит выражение "Новый".
	// Для совместимости с OneScript поддерживается	
	// обращение к конструктору через точку (поле Хвост)
	// Пример:
	// <pre>
	// // выражения "Новый" заключены в скобки {...}
	// // в этом варианте поле "Имя" хранит имя типа "Массив",
	// // а поле "Аргументы" хранит массив из одного выражения
	// Параметры = {Новый Массив(1)};
	// Параметры[0] = 10;
	// // в этом варианте поле "Имя" равно Неопределено,
	// // а поле "Аргументы" хранит массив из двух выражений
	// Массив = {Новый (Тип("Массив"), Параметры)};
	// </pre>
	// Инвариант: если (ВыражениеНовый.Имя = Неопределено) то (0 < ВыражениеНовый.Аргументы.Количество() <= 2)
	Поля = Парсер_Узлы.ВыражениеНовый.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Имя"); // неопределено, строка
	Поля.Добавить("Аргументы"); // массив (один из #Выражения)
	Поля.Добавить("Хвост"); // массив (ВыражениеПоле, ВыражениеИндекс)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ВыражениеТернарное", Новый ТаблицаЗначений);
	// Хранит тернарное выражение "?(,,)".
	// Пример:
	// <pre>
	// Значение = ?(Ложь,   // поле "Выражение"
	//     Неопределено,    // поле "Тогда"
	//     Новый Массив     // поле "Иначе"
	// ).Количество();      // поле "Хвост"
	// </pre>
	Поля = Парсер_Узлы.ВыражениеТернарное.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Выражение"); // структура (один из #Выражения)
	Поля.Добавить("Тогда"); // структура (один из #Выражения)
	Поля.Добавить("Иначе"); // структура (один из #Выражения)
	Поля.Добавить("Хвост"); // массив (ВыражениеПоле, ВыражениеИндекс)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ВыражениеСкобочное", Новый ТаблицаЗначений);
	// Хранит скобочное выражение.
	// Пример:
	// <pre>
	// // скобочное выражение заключено в скобки {...}
	// Сумма = {(Сумма1 + Сумма2)} * Количество;
	// </pre>
	Поля = Парсер_Узлы.ВыражениеСкобочное.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Выражение"); // структура (один из #Выражения)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ВыражениеНе", Новый ТаблицаЗначений);
	// Хранит выражение, к которому применено логическое отрицание "Не".
	// Пример:
	// <pre>
	// // выражение-отрицание заключено в скобки {...}
	// НеРавны = {Не Сумма1 = Сумма2};
	// </pre>
	Поля = Парсер_Узлы.ВыражениеНе.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Выражение"); // структура (один из #Выражения)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ВыражениеСтроковое", Новый ТаблицаЗначений);
	// Хранит строковое выражение.
	// Поле "Элементы" хранит упорядоченный список частей строки.
	// Пример:
	// <pre>
	// Строка1 = "Часть1" "Часть2"; // эта строка состоит из двух частей типа Типы.Строка
	// Строка2 =                    // эта строка состоит из пяти частей типа:
	// "Начало строки               // Типы.НачалоСтроки
	// | продолжение строки         // Типы.ПродолжениеСтроки
	// | еще продолжение строки     // Типы.ПродолжениеСтроки
	// | окончание строки"          // Типы.ОкончаниеСтроки
	// "еще часть";                 // Типы.Строка
	// </pre>
	Поля = Парсер_Узлы.ВыражениеСтроковое.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Элементы"); // массив (ВыражениеЛитерал)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ВыражениеЖдать", Новый ТаблицаЗначений);
	// Хранит выражение "Ждать".
	// Пример:
	// <pre>
	// Результат = {Ждать ПредупреждениеАсинх(Текст)};
	// </pre>
	Поля = Парсер_Узлы.ВыражениеЖдать.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Выражение"); // структура (один из #Выражения)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
КонецПроцедуры 

Процедура ИнициализироватьОператоры()
	
	Парсер_Узлы.Вставить("ОператорПрисваивания", Новый ТаблицаЗначений);
	// Хранит оператор присваивания.
	Поля = Парсер_Узлы.ОператорПрисваивания.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("ЛевыйОперанд"); // структура (ВыражениеИдентификатор)
	Поля.Добавить("ПравыйОперанд"); // структура (один из #Выражения)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОператорВозврат", Новый ТаблицаЗначений);
	// Хранит оператор "Возврат".
	// Поле "Выражение" равно Неопределено если это возврат из процедуры.
	Поля = Парсер_Узлы.ОператорВозврат.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Выражение"); // неопределено, структура (один из #Выражения)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОператорПрервать", Новый ТаблицаЗначений);
	// Хранит оператор "Прервать".
	Поля = Парсер_Узлы.ОператорПрервать.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОператорПродолжить", Новый ТаблицаЗначений);
	// Хранит оператор "Продолжить".
	Поля = Парсер_Узлы.ОператорПродолжить.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОператорВызватьИсключение", Новый ТаблицаЗначений);
	// Хранит оператор "ВызватьИсключение".
	// Поле "Выражение" равно Неопределено если это вариант оператора без выражения.
	Поля = Парсер_Узлы.ОператорВызватьИсключение.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Выражение"); // неопределено, структура (один из #Выражения)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОператорВыполнить", Новый ТаблицаЗначений);
	// Хранит оператор "Выполнить".
	Поля = Парсер_Узлы.ОператорВыполнить.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Выражение"); // структура (один из #Выражения)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОператорВызоваПроцедуры", Новый ТаблицаЗначений);
	// Хранит вызов процедуры или функции как процедуры.
	Поля = Парсер_Узлы.ОператорВызоваПроцедуры.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Идентификатор"); // структура (ВыражениеИдентификатор)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОператорЕсли", Новый ТаблицаЗначений);
	// Хранит оператор "Если".
	// Пример:
	// <pre>
	// Если Сумма > 0 Тогда // поле "Выражение" хранит условие (выражение)
	//     // поле "Тогда" хранит операторы в этом блоке
	// ИначеЕсли Сумма = 0 Тогда
	//     // поле-массив "ИначеЕсли" хранит последовательность блоков ИначеЕсли
	// Иначе
	//     // поле "Иначе" хранит операторы в этом блоке
	// КонецЕсли
	// </pre>
	// Поля "ИначеЕсли" и "Иначе" равны Неопределено если
	// соответствующие блоки отсутствуют в исходном коде.
	Поля = Парсер_Узлы.ОператорЕсли.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Выражение"); // структура (один из #Выражения)
	Поля.Добавить("Тогда"); // массив (один из #Операторы)
	Поля.Добавить("ИначеЕсли"); // неопределено, массив (ОператорИначеЕсли)
	Поля.Добавить("Иначе"); // неопределено, структура (ОператорИначе)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОператорИначе", Новый ТаблицаЗначений);
	// Хранит блок "Иначе"
	Поля = Парсер_Узлы.ОператорИначе.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Операторы"); // массив (один из #Операторы)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОператорИначеЕсли", Новый ТаблицаЗначений);
	// Хранит блок "ИначеЕсли" оператора "Если".
	// Пример:
	// <pre>
	// ...
	// ИначеЕсли Сумма < 0 Тогда // поле "Выражение" хранит условие (выражение)
	//     // поле "Тогда" хранит операторы в этом блоке
	// ...
	// </pre>
	Поля = Парсер_Узлы.ОператорИначеЕсли.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Выражение"); // структура (один из #Выражения)
	Поля.Добавить("Тогда"); // массив (один из #Операторы)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОператорПока", Новый ТаблицаЗначений);
	// Хранит оператор цикла "Пока".
	// Пример:
	// <pre>
	// Пока Индекс > 0 Цикл // поле "Выражение" хранит условие (выражение)
	//     // поле "Операторы" хранит операторы в этом блоке
	// КонецЦикла
	// </pre>
	Поля = Парсер_Узлы.ОператорПока.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Выражение"); // структура (один из #Выражения)
	Поля.Добавить("Операторы"); // массив (один из #Операторы)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОператорДля", Новый ТаблицаЗначений);
	// Хранит оператор цикла "Для".
	// Пример:
	// <pre>
	// Для Индекс = 0      // поля "Идентификатор" и "Старт" хранят переменную и выражение инициализации.
	//   По Длина - 1 Цикл // поле "Финиш" хранит выражение границы
	//     // поле "Операторы" хранит операторы в этом блоке
	// КонецЦикла
	// </pre>
	Поля = Парсер_Узлы.ОператорДля.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Идентификатор"); // структура (ВыражениеИдентификатор)
	Поля.Добавить("Старт"); // структура (один из #Выражения)
	Поля.Добавить("Финиш"); // структура (один из #Выражения)
	Поля.Добавить("Операторы"); // массив (один из #Операторы)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОператорДляКаждого", Новый ТаблицаЗначений);
	// Хранит оператор цикла "Для Каждого".
	// Пример:
	// <pre>
	// Для Каждого Элемент // поле "Идентификатор" хранит переменную.
	//   Из Список Цикл    // поле "Коллекция" хранит выражение коллекции.
	//     // поле "Операторы" хранит операторы в этом блоке
	// КонецЦикла
	// </pre>
	Поля = Парсер_Узлы.ОператорДляКаждого.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Идентификатор"); // структура (ВыражениеИдентификатор)
	Поля.Добавить("Коллекция"); // структура (один из #Выражения)
	Поля.Добавить("Операторы"); // массив (один из #Операторы)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОператорПопытка", Новый ТаблицаЗначений);
	// Хранит оператор "Попытка"
	// Пример:
	// <pre>
	// Попытка
	//     // поле "Попытка" хранит операторы в этом блоке.
	// Исключение
	//     // поле "Исключение" хранит операторы в этом блоке
	// КонецПопытки
	// </pre>
	Поля = Парсер_Узлы.ОператорПопытка.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Попытка"); // массив (один из #Операторы)
	Поля.Добавить("Исключение"); // структура (ОператорИсключение)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОператорИсключение", Новый ТаблицаЗначений);
	// Хранит блок "Исключение"
	Поля = Парсер_Узлы.ОператорИсключение.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Операторы"); // массив (один из #Операторы)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОператорПерейти", Новый ТаблицаЗначений);
	// Хранит оператор "Перейти"
	Поля = Парсер_Узлы.ОператорПерейти.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Метка"); // строка
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОператорМетка", Новый ТаблицаЗначений);
	// Хранит оператор метки.
	Поля = Парсер_Узлы.ОператорМетка.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Метка"); // строка
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОператорДобавитьОбработчик", Новый ТаблицаЗначений);
	// Хранит оператор "ДобавитьОбработчик".
	Поля = Парсер_Узлы.ОператорДобавитьОбработчик.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Событие"); // структура (ВыражениеИдентификатор)
	Поля.Добавить("ОбработчикСобытия"); // структура (ВыражениеИдентификатор)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ОператорУдалитьОбработчик", Новый ТаблицаЗначений);
	// Хранит оператор "УдалитьОбработчик".
	Поля = Парсер_Узлы.ОператорУдалитьОбработчик.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Событие"); // структура (ВыражениеИдентификатор)
	Поля.Добавить("ОбработчикСобытия"); // структура (ВыражениеИдентификатор)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
КонецПроцедуры 

Процедура ИнициализироватьИнструкцииПрепроцессора()
	
	Парсер_Узлы.Вставить("ИнструкцияПрепроцессораЕсли", Новый ТаблицаЗначений);
	// Хранит информацию об инструкции препроцессора #Если,
	// Пример:
	// <pre>
	// ...
	// #Если Сервер Тогда // поле "Выражение" хранит условие (выражение)
	// ...
	// </pre>
	Поля = Парсер_Узлы.ИнструкцияПрепроцессораЕсли.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Выражение"); // структура (один из #ВыражениеПрепроцессора)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ИнструкцияПрепроцессораИначеЕсли", Новый ТаблицаЗначений);
	// Хранит информацию об инструкции препроцессора #ИначеЕсли
	// Пример:
	// <pre>
	// ...
	// #ИначеЕсли Клиент Тогда // поле "Выражение" хранит условие (выражение)
	// ...
	// </pre>
	Поля = Парсер_Узлы.ИнструкцияПрепроцессораИначеЕсли.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Выражение"); // структура (один из #ВыражениеПрепроцессора)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ИнструкцияПрепроцессораИначе", Новый ТаблицаЗначений);
	// Хранит информацию об инструкции препроцессора #Иначе
	Поля = Парсер_Узлы.ИнструкцияПрепроцессораИначе.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ИнструкцияПрепроцессораКонецЕсли", Новый ТаблицаЗначений);
	// Хранит информацию об инструкции препроцессора #КонецЕсли
	Поля = Парсер_Узлы.ИнструкцияПрепроцессораКонецЕсли.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ИнструкцияПрепроцессораОбласть", Новый ТаблицаЗначений);
	// Хранит информацию об инструкции препроцессора #Обрасть,
	// Пример:
	// <pre>
	// ...
	//#Область Интерфейс   // поле "Имя" хранит имя области
	// ...
	// </pre>
	Поля = Парсер_Узлы.ИнструкцияПрепроцессораОбласть.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Имя"); // строка
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ИнструкцияПрепроцессораКонецОбласти", Новый ТаблицаЗначений);
	// Хранит информацию об инструкции препроцессора #КонецОбласти,
	// Пример:
	// <pre>
	// ...
	//#КонецОбласти
	// ...
	// </pre>
	Поля = Парсер_Узлы.ИнструкцияПрепроцессораКонецОбласти.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ИнструкцияПрепроцессораВставка", Новый ТаблицаЗначений);
	// Хранит информацию об инструкции препроцессора #Вставка,
	// Пример:
	// <pre>
	// ...
	//#Вставка
	// ...
	// </pre>
	Поля = Парсер_Узлы.ИнструкцияПрепроцессораВставка.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ИнструкцияПрепроцессораКонецВставки", Новый ТаблицаЗначений);
	// Хранит информацию об инструкции препроцессора #КонецВставки,
	// Пример:
	// <pre>
	// ...
	//#КонецВставки
	// ...
	// </pre>
	Поля = Парсер_Узлы.ИнструкцияПрепроцессораКонецВставки.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ИнструкцияПрепроцессораУдаление", Новый ТаблицаЗначений);
	// Хранит информацию об инструкции препроцессора #Удаление,
	// Пример:
	// <pre>
	// ...
	//#Удаление
	// ...
	// </pre>
	Поля = Парсер_Узлы.ИнструкцияПрепроцессораУдаление.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ИнструкцияПрепроцессораКонецУдаления", Новый ТаблицаЗначений);
	// Хранит информацию об инструкции препроцессора #КонецУдаления,
	// Пример:
	// <pre>
	// ...
	//#КонецУдаления
	// ...
	// </pre>
	Поля = Парсер_Узлы.ИнструкцияПрепроцессораКонецУдаления.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ИнструкцияПрепроцессораИспользовать", Новый ТаблицаЗначений);
	// Хранит информацию об инструкции препроцессора #Использовать,
	// Пример:
	// <pre>
	// ...
	//#Использовать osparser
	// ...
	// </pre>
	Поля = Парсер_Узлы.ИнструкцияПрепроцессораИспользовать.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Путь"); // строка
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
КонецПроцедуры 

Процедура ИнициализироватьВыраженияПрепроцессора()
	
	Парсер_Узлы.Вставить("ВыражениеПрепроцессораБинарное", Новый ТаблицаЗначений);
	// Хранит бинарное выражение препроцессора.
	// Пример:
	// <pre>
	// // бинарные выражения заключены в скобки {...}
	// // поле "Операция.Токен" равно либо Токены.Или либо Токены.И:
	// // поля "ЛевыйОперанд" и "ПравыйОперанд" содержат операнды-выражения препроцессора
	// #Если {Сервер Или ВнешнееСоединение} Тогда
	// ...
	// </pre>
	Поля = Парсер_Узлы.ВыражениеПрепроцессораБинарное.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("ЛевыйОперанд"); // структура (один из #ВыражениеПрепроцессора)
	Поля.Добавить("Операция"); // один из ТаблицаТокенов
	Поля.Добавить("ПравыйОперанд"); // структура (один из #ВыражениеПрепроцессора)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ВыражениеПрепроцессораНе", Новый ТаблицаЗначений);
	// Хранит выражение препроцессора, к которому применено логическое отрицание "Не".
	// Пример:
	// <pre>
	// // выражение-отрицание заключено в скобки {...}
	// #Если {Не ВебКлиент} Тогда
	// ...
	// </pre>
	Поля = Парсер_Узлы.ВыражениеПрепроцессораНе.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Выражение"); // структура (один из #ВыражениеПрепроцессора)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ВыражениеПрепроцессораСимвол", Новый ТаблицаЗначений);
	// Узел хранит информацию о символе препроцессора.
	// Поле Существует = Истина если такой символ существует.
	// Пример:
	// <pre>
	// // символ заключен в скобки {...}
	// #Если {Сервер} Тогда
	// </pre>
	Поля = Парсер_Узлы.ВыражениеПрепроцессораСимвол.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Символ"); // строка (один из PrepСимволs)
	Поля.Добавить("Существует"); // булево
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
	Парсер_Узлы.Вставить("ВыражениеПрепроцессораСкобочное", Новый ТаблицаЗначений);
	// Хранит скобочное выражение препроцессора.
	// Пример:
	// <pre>
	// // скобочное выражение заключено в скобки {...}
	// #Если {(Сервер Или ВнешнееСоединение)} Тогда
	// </pre>
	Поля = Парсер_Узлы.ВыражениеПрепроцессораСкобочное.Колонки;
	Поля.Добавить("Тип"); // строка (один из Типы)
	Поля.Добавить("Выражение"); // структура (один из #ВыражениеПрепроцессора)
	Поля.Добавить("Начало"); // один из ТаблицаТокенов
	Поля.Добавить("Конец"); // один из ТаблицаТокенов
	
КонецПроцедуры 

#КонецОбласти // Инициализация

#Область Перечисления

Функция КлючевыеСлова() Экспорт
	Возврат Перечисление(Новый Структура,
	"Если.If, Тогда.Then, ИначеЕсли.ElsIf, Иначе.Else, КонецЕсли.EndIf,
	|Для.For, Каждого.Each, Из.In, По.To, Пока.While, Цикл.Do, КонецЦикла.EndDo,
	|Процедура.Procedure, КонецПроцедуры.EndProcedure, Функция.Function, КонецФункции.EndFunction,
	|Перем.Var, Знач.Val, Возврат.Return, Продолжить.Continue, Прервать.Break,
	|И.And, Или.Or, Не.Not, ДобавитьОбработчик.AddHandler, УдалитьОбработчик.RemoveHandler,
	|Попытка.Try, Исключение.Except, ВызватьИсключение.Raise, КонецПопытки.EndTry,
	|Новый.New, Выполнить.Execute, Экспорт.Export, Перейти.Goto,
	|Асинх.Async, Ждать.Await,
	|Истина.True, Ложь.False, Неопределено.Undefined, Null"
);
КонецФункции // КлючевыеСлова()

Функция Токены(КлючевыеСлова = Неопределено) Экспорт
	Перем Токены;
	
	Если КлючевыеСлова = Неопределено Тогда
		КлючевыеСлова = КлючевыеСлова();
	КонецЕсли;
	
	Токены = Перечисление(Новый Структура(КлючевыеСлова),
	
	// Литералы
	
	"Идентификатор, Число, Строка, ДатаВремя,
	// Элементы строк
	|НачалоСтроки, ПродолжениеСтроки, ОкончаниеСтроки,
	
	// Операции
	
	//       =           <>           <           >
	|ЗнакРавно, ЗнакНеРавно, ЗнакМеньше, ЗнакБольше,
	//               <=                  >=
	|ЗнакМеньшеИлиРавно, ЗнакБольшеИлиРавно,
	//          +              -              *            /            %
	|ЗнакСложения, ЗнакВычитания, ЗнакУмножения, ЗнакДеления, ЗнакОстатка,
	//                (                    )                      [                       ]
	|ЛеваяКруглаяСкобка, ПраваяКруглаяСкобка, ЛеваяКвадратнаяСкобка, ПраваяКвадратнаяСкобка,
	//         ?        ,      .          :              ;
	|ЗнакВопроса, Запятая, Точка, Двоеточие, ТочкаСЗапятой,
	
	// ИнструкцииПрепроцессора
	|_Если, _ИначеЕсли, _Иначе, _КонецЕсли, _Область, _КонецОбласти,
	|_Вставка, _КонецВставки, _Удаление, _КонецУдаления, _Использовать,
	
	// Другие
	
	//        //      ~          &          &
	|Комментарий, Метка, Аннотация, Директива, НачалоТекста, КонецТекста,"
	
);

Возврат Токены;
КонецФункции // Токены()

Функция Типы() Экспорт
	Возврат Перечисление(Новый Структура,
	"Модуль, ЭлементОкружения, ОбъявлениеГлобальногоОбъекта, ОбъявлениеГлобальногоМетода,
	|ОбъявлениеДирективы, ОбъявлениеАннотации, ОбъявлениеПеременнойМодуля, ОбъявлениеСпискаПеременныхМодуля,
	|ОбъявлениеСпискаЛокальныхПеременных, ОбъявлениеЛокальнойПеременной, ОбъявлениеАвтоПеременной,
	|ОбъявлениеПараметра, ОбъявлениеМетода, ОбъявлениеСигнатурыПроцедуры, ОбъявлениеСигнатурыФункции,
	|ВыражениеЛитерал, ВыражениеПоле, ВыражениеИндекс, ВыражениеИдентификатор,
	|ВыражениеУнарное, ВыражениеБинарное, ВыражениеНовый, ВыражениеТернарное,
	|ВыражениеСкобочное, ВыражениеНе, ВыражениеСтроковое,
	|ОператорПрисваивания, ОператорВозврат, ОператорПрервать, ОператорПродолжить,
	|ОператорВызватьИсключение, ОператорВыполнить, ОператорПока, ОператорДля, ОператорДляКаждого,
	|ОператорПопытка, ОператорИсключение, ОператорПерейти, ОператорМетка,
	|ОператорВызоваПроцедуры, ОператорЕсли, ОператорИначеЕсли, ОператорИначе,
	|ОператорДобавитьОбработчик, ОператорУдалитьОбработчик,
	|ИнструкцияПрепроцессораЕсли, ИнструкцияПрепроцессораИначеЕсли, ИнструкцияПрепроцессораИначе,
	|ИнструкцияПрепроцессораКонецЕсли, ИнструкцияПрепроцессораОбласть, ИнструкцияПрепроцессораКонецОбласти,
	|ИнструкцияПрепроцессораВставка, ИнструкцияПрепроцессораКонецВставки,
	|ИнструкцияПрепроцессораУдаление, ИнструкцияПрепроцессораКонецУдаления,
	|ИнструкцияПрепроцессораИспользовать,
	|ВыражениеЖдать,
	|ВыражениеПрепроцессораБинарное, ВыражениеПрепроцессораНе,
	|ВыражениеПрепроцессораСимвол, ВыражениеПрепроцессораСкобочное"
);
КонецФункции // Типы()

Функция Директивы() Экспорт
	Возврат Перечисление(Новый Структура,
	"НаКлиенте.AtClient,"
	"НаСервере.AtServer,"
	"НаСервереБезКонтекста.AtServerNoContext,"
	"НаКлиентеНаСервереБезКонтекста.AtClientAtServerNoContext,"
	"НаКлиентеНаСервере.AtClientAtServer"
);
КонецФункции // Директивы()

Функция Аннотации() Экспорт
	Возврат Перечисление(Новый Структура,
	"Перед.Before,"
	"После.After,"
	"Вместо.Around,"
	"ИзменениеИКонтроль.ChangeAndValidate,"
);
КонецФункции // Аннотации()

Функция ИнструкцииПрепроцессора()
	Возврат Перечисление(Новый Структура,
	"Если.If,"
	"ИначеЕсли.ElsIf,"
	"Иначе.Else,"
	"КонецЕсли.EndIf,"
	"Область.Region,"
	"КонецОбласти.EndRegion,"
	"Вставка.Insert,"
	"КонецВставки.EndInsert,"
	"Удаление.Delete,"
	"КонецУдаления.EndDelete,"
	"Использовать.Use,"
);
КонецФункции // ИнструкцииПрепроцессора()

Функция СимволыПрепроцессора() Экспорт
	Возврат Перечисление(Новый Структура,
	"Клиент.Client,"
	"НаКлиенте.AtClient,"
	"НаСервере.AtServer,"
	"МобильноеПриложениеКлиент.MobileAppClient,"
	"МобильноеПриложениеСервер.MobileAppServer,"
	"ТолстыйКлиентОбычноеПриложение.ThickClientOrdinaryApplication,"
	"ТолстыйКлиентУправляемоеПриложение.ThickClientManagedApplication,"
	"Сервер.Server,"
	"ВнешнееСоединение.ExternalConnection,"
	"ТонкийКлиент.ThinClient,"
	"ВебКлиент.WebClient"
);
КонецФункции // СимволыПрепроцессора()

Функция Перечисление(Структура, Ключи)
	Перем Элементы, Имя, Имена, Значение;
	
	Для Каждого Элементы Из СтрРазделить(Ключи, ",", Ложь) Цикл
		Имена = СтрРазделить(Элементы, ".", Ложь);
		Значение = СокрЛП(Имена[0]);
		Для Каждого Имя Из Имена Цикл
			Структура.Вставить(СокрЛП(Имя), Значение);
		КонецЦикла;
	КонецЦикла;
	
	Возврат Новый ФиксированнаяСтруктура(Структура);
КонецФункции // Перечисление()

#КонецОбласти // Перечисления

#Область Парсер

Функция СледующийТокен()
	Перем Начало, ПредыдущийСимвол, Комментарий, ДанныеТокена;
	
	Парсер_Значение = Неопределено;
	
	Если Прав(Парсер_Литерал, 1) = Символы_ПС Тогда
		Парсер_НомерТекущейСтроки = Парсер_НомерТекущейСтроки + 1;
		Парсер_ПозицияТекущейСтроки = Парсер_ТекущаяПозиция - 1;
	КонецЕсли;
	
	Пока Истина Цикл
		
		Комментарий = Ложь;
		
		// пропуск невидимых символов
		Пока ПустаяСтрока(Парсер_Символ) И Парсер_Символ <> "" Цикл
			Если Парсер_Символ = Символы_ПС Тогда
				Парсер_НомерТекущейСтроки = Парсер_НомерТекущейСтроки + 1;
				Парсер_ПозицияТекущейСтроки = Парсер_ТекущаяПозиция;
			КонецЕсли;
			Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
			Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
		КонецЦикла;
		
		Парсер_ПозицияНачалаТокена = Парсер_ТекущаяПозиция;
		
		Парсер_Токен = КартаТокенов[Парсер_Символ];
		Если Парсер_Токен = Буква Тогда
			
			// сканирование идентификатора
			Начало = Парсер_ТекущаяПозиция;
			Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
			Пока КартаБуквЦифр[Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1)] <> Неопределено Цикл
				Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
			КонецЦикла;
			Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
			Парсер_Литерал = Сред(Парсер_Исходник, Начало, Парсер_ТекущаяПозиция - Начало);
			
			// определение токена
			Если КлючевыеСлова.Свойство(Парсер_Литерал, Парсер_Токен) Тогда
				Если Парсер_Токен = Токены.Истина Тогда
					Парсер_Значение = Истина;
				ИначеЕсли Парсер_Токен = Токены.Ложь Тогда
					Парсер_Значение = Ложь;
				ИначеЕсли Парсер_Токен = Токены.Null Тогда
					Парсер_Значение = Null;
				КонецЕсли;
			Иначе
				Парсер_Токен = Токены.Идентификатор;
			КонецЕсли;
			
		ИначеЕсли Парсер_Токен = Токены.НачалоСтроки Тогда
			
			Начало = Парсер_ТекущаяПозиция;
			Парсер_Символ = """"; // уловка
			Пока Парсер_Символ = """" Цикл
				Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
				Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
				Пока Парсер_Символ <> """" И Парсер_Символ <> Символы_ПС И Парсер_Символ <> "" Цикл
					Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
					Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
				КонецЦикла;
				Если Парсер_Символ <> "" Тогда
					Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
					Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
				КонецЕсли;
			КонецЦикла;
			
			Парсер_Литерал = Сред(Парсер_Исходник, Начало, Парсер_ТекущаяПозиция - Начало);
			Парсер_Значение = СтрЗаменить(Сред(Парсер_Литерал, 2, СтрДлина(Парсер_Литерал) - 2), """""", """");
			Если Прав(Парсер_Литерал, 1) = """" Тогда
				Парсер_Токен = Токены.Строка;
			КонецЕсли;
			
		ИначеЕсли Парсер_Токен = Токены.ПродолжениеСтроки Тогда
			
			Начало = Парсер_ТекущаяПозиция;
			Парсер_Символ = """"; // уловка
			Пока Парсер_Символ = """" Цикл
				Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
				Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
				Пока Парсер_Символ <> """" И Парсер_Символ <> Символы_ПС И Парсер_Символ <> "" Цикл
					Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
					Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
				КонецЦикла;
				Если Парсер_Символ <> "" Тогда
					Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
					Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
				КонецЕсли;
			КонецЦикла;
			
			Парсер_Литерал = Сред(Парсер_Исходник, Начало, Парсер_ТекущаяПозиция - Начало);
			Парсер_Значение = СтрЗаменить(Сред(Парсер_Литерал, 2, СтрДлина(Парсер_Литерал) - 2), """""", """");
			Если Прав(Парсер_Литерал, 1) = """" Тогда
				Парсер_Токен = Токены.ОкончаниеСтроки;
			КонецЕсли;
			
		ИначеЕсли Парсер_Токен = Цифра Тогда
			
			Начало = Парсер_ТекущаяПозиция;
			Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
			Пока КартаБуквЦифр[Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1)] = Цифра Цикл
				Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
			КонецЦикла;
			Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
			Если Парсер_Символ = "." Тогда
				Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
				Пока КартаБуквЦифр[Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1)] = Цифра Цикл
					Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
				КонецЦикла;
				Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
			КонецЕсли;
			Парсер_Литерал = Сред(Парсер_Исходник, Начало, Парсер_ТекущаяПозиция - Начало);
			
			Парсер_Значение = Число(Парсер_Литерал);
			Парсер_Токен = Токены.Число;
			
		ИначеЕсли Парсер_Токен = Токены.ДатаВремя Тогда
			
			Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
			Начало = Парсер_ТекущаяПозиция;
			Парсер_ТекущаяПозиция = СтрНайти(Парсер_Исходник, "'", , Парсер_ТекущаяПозиция);
			Если Парсер_ТекущаяПозиция = 0 Тогда
				Парсер_Символ = "";
			Иначе
				Парсер_Литерал = Сред(Парсер_Исходник, Начало, Парсер_ТекущаяПозиция - Начало);
				Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
				Парсер_Значение = КакДата(Парсер_Литерал);
				Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
			КонецЕсли;
			
		ИначеЕсли Парсер_Токен = Неопределено Тогда
			
			ПредыдущийСимвол = Парсер_Символ;
			Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
			Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
			
			Если ПредыдущийСимвол = "/" Тогда
				
				Если Парсер_Символ = "/" Тогда
					// сканирование комментария
					Начало = Парсер_ТекущаяПозиция + 1;
					Если Начало < Парсер_ДлинаИсходника Тогда
						Парсер_ТекущаяПозиция = СтрНайти(Парсер_Исходник, Символы_ПС, , Начало);
					Иначе
						Парсер_ТекущаяПозиция = 0;
					КонецЕсли;
					Если Парсер_ТекущаяПозиция = 0 Тогда
						Парсер_ТекущаяПозиция = Парсер_ДлинаИсходника + 1;
						Парсер_Символ = "";
					Иначе
						Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
					КонецЕсли;
					Парсер_ИндексТокена = Парсер_ИндексТокена + 1;
					ДанныеТокена = Парсер_Токены.Добавить();
					ДанныеТокена.Индекс = Парсер_ИндексТокена;
					ДанныеТокена.Токен = Токены.Комментарий;
					ДанныеТокена.НомерСтроки = Парсер_НомерТекущейСтроки;
					ДанныеТокена.НомерКолонки = Парсер_ПозицияНачалаТокена + 2 - Парсер_ПозицияТекущейСтроки;
					ДанныеТокена.Позиция = Парсер_ПозицияНачалаТокена + 2;
					ДанныеТокена.Длина = Парсер_ТекущаяПозиция - ДанныеТокена.Позиция; 
					Комментарий = Истина;
				Иначе
					Парсер_Токен = Токены.ЗнакДеления;
				КонецЕсли;
				
			ИначеЕсли ПредыдущийСимвол = "<" Тогда
				
				Если Парсер_Символ = ">" Тогда
					Парсер_Токен = Токены.ЗнакНеРавно;
					Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
					Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
				ИначеЕсли Парсер_Символ = "=" Тогда
					Парсер_Токен = Токены.ЗнакМеньшеИлиРавно;
					Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
					Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
				Иначе
					Парсер_Токен = Токены.ЗнакМеньше;
				КонецЕсли;
				
			ИначеЕсли ПредыдущийСимвол = ">" Тогда
				
				Если Парсер_Символ = "=" Тогда
					Парсер_Токен = Токены.ЗнакБольшеИлиРавно;
					Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
					Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
				Иначе
					Парсер_Токен = Токены.ЗнакБольше;
				КонецЕсли;
				
			ИначеЕсли ПредыдущийСимвол = "&" Тогда
				
				Если КартаБуквЦифр[Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1)] <> Буква Тогда
					Ошибка(2, Неопределено, Истина);
				КонецЕсли;
				
				// сканирование идентификатора
				Начало = Парсер_ТекущаяПозиция;
				Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
				Пока КартаБуквЦифр[Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1)] <> Неопределено Цикл
					Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
				КонецЦикла;
				Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
				Парсер_Литерал = Сред(Парсер_Исходник, Начало, Парсер_ТекущаяПозиция - Начало);
				
				Если Директивы.Свойство(Парсер_Литерал) Тогда
					Парсер_Токен = Токены.Директива;	
				ИначеЕсли Аннотации.Свойство(Парсер_Литерал) Тогда
					Парсер_Токен = Токены.Аннотация;
				Иначе
					Ошибка(3, Парсер_Литерал, Ложь);
					Парсер_Токен = Токены.Директива;
				КонецЕсли;
				
			ИначеЕсли ПредыдущийСимвол = "#" Тогда
				
				// пропуск невидимых символов
				Пока ПустаяСтрока(Парсер_Символ) И Парсер_Символ <> "" Цикл
					Если Парсер_Символ = Символы_ПС Тогда
						Парсер_НомерТекущейСтроки = Парсер_НомерТекущейСтроки + 1;
						Парсер_ПозицияТекущейСтроки = Парсер_ТекущаяПозиция;
					КонецЕсли;
					Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
					Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
				КонецЦикла;
				
				Если КартаБуквЦифр[Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1)] <> Буква Тогда
					Ошибка(4, Неопределено, Истина);
				КонецЕсли;
				
				// сканирование идентификатора
				Начало = Парсер_ТекущаяПозиция;
				Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
				Пока КартаБуквЦифр[Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1)] <> Неопределено Цикл
					Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
				КонецЦикла;
				Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
				Парсер_Литерал = Сред(Парсер_Исходник, Начало, Парсер_ТекущаяПозиция - Начало);
				
				// сопоставление токена
				Если ИнструкцииПрепроцессора.Свойство(Парсер_Литерал, Парсер_Токен) Тогда
					Парсер_Токен = "_" + Парсер_Токен;
				Иначе
					Ошибка(5, Парсер_Литерал, Истина);
				КонецЕсли;
				
			ИначеЕсли ПредыдущийСимвол = "~" Тогда
				
				// пропуск невидимых символов
				Пока ПустаяСтрока(Парсер_Символ) И Парсер_Символ <> "" Цикл
					Если Парсер_Символ = Символы_ПС Тогда
						Парсер_НомерТекущейСтроки = Парсер_НомерТекущейСтроки + 1;
						Парсер_ПозицияТекущейСтроки = Парсер_ТекущаяПозиция;
					КонецЕсли;
					Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
					Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
				КонецЦикла;
				
				Если КартаБуквЦифр[Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1)] = Неопределено Тогда
					Парсер_Литерал = "";
				Иначе
					// сканирование идентификатора
					Начало = Парсер_ТекущаяПозиция;
					Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
					Пока КартаБуквЦифр[Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1)] <> Неопределено Цикл
						Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
					КонецЦикла;
					Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
					Парсер_Литерал = Сред(Парсер_Исходник, Начало, Парсер_ТекущаяПозиция - Начало);
				КонецЕсли;
				
				Парсер_Токен = Токены.Метка;
				
			Иначе
				
				ВызватьИсключение "Неизвестный символ!";
				
			КонецЕсли;
			
		Иначе
			
			Парсер_Литерал = Парсер_Символ;
			Парсер_ТекущаяПозиция = Парсер_ТекущаяПозиция + 1;
			Парсер_Символ = Сред(Парсер_Исходник, Парсер_ТекущаяПозиция, 1);
			
		КонецЕсли;
		
		Если Не Комментарий Тогда
			Прервать;
		КонецЕсли;
		
	КонецЦикла;
	
	Парсер_ДанныеПредыдущегоТокена = Парсер_ДанныеТекущегоТокена;
	
	Парсер_ИндексТокена = Парсер_ИндексТокена + 1;
	
	Парсер_ДанныеТекущегоТокена = Парсер_Токены.Добавить();
	Парсер_ДанныеТекущегоТокена.Индекс = Парсер_ИндексТокена;
	Парсер_ДанныеТекущегоТокена.Токен = Парсер_Токен;
	Парсер_ДанныеТекущегоТокена.НомерСтроки = Парсер_НомерТекущейСтроки;
	Парсер_ДанныеТекущегоТокена.НомерКолонки = Парсер_ПозицияНачалаТокена - Парсер_ПозицияТекущейСтроки;
	Парсер_ДанныеТекущегоТокена.Позиция = Парсер_ПозицияНачалаТокена;
	Парсер_ДанныеТекущегоТокена.Длина = Парсер_ТекущаяПозиция - Парсер_ДанныеТекущегоТокена.Позиция;
	
	Возврат Парсер_Токен;
	
КонецФункции // СледующийТокен()

Функция Окружение(ВнешнееОкружение = Неопределено) Экспорт
	Возврат Новый Структура(
	"ВнешнееОкружение," // неопределено, структура (Окружение)
	"Переменные,"       // структура как соответствие[строка] (ЭлементОкружения)
	"Методы,"           // структура как соответствие[строка] (ЭлементОкружения)
	"АвтоПеременные",   // массив (ОбъявлениеАвтоПеременной)
	ВнешнееОкружение, Новый Структура, Новый Структура, Новый Массив);
КонецФункции // Окружение()

Функция НайтиЭлементОкружения(Имя)
	Перем Окружение, ЭлементОкружения;
	Окружение = Парсер_Окружение;
	Окружение.Переменные.Свойство(Имя, ЭлементОкружения);
	Пока ЭлементОкружения = Неопределено И Окружение.ВнешнееОкружение <> Неопределено Цикл
		Окружение = Окружение.ВнешнееОкружение;
		Окружение.Переменные.Свойство(Имя, ЭлементОкружения);
	КонецЦикла;
	Возврат ЭлементОкружения;
КонецФункции // НайтиЭлементОкружения()

Функция НайтиМетод(Имя)
	Перем Окружение, Метод;
	Окружение = Парсер_Окружение;
	Окружение.Методы.Свойство(Имя, Метод);
	Пока Метод = Неопределено И Окружение.ВнешнееОкружение <> Неопределено Цикл
		Окружение = Окружение.ВнешнееОкружение;
		Окружение.Методы.Свойство(Имя, Метод);
	КонецЦикла;
	Возврат Метод;
КонецФункции

Функция ОткрытьОкружение()
	Перем Окружение;
	Окружение = Окружение(Парсер_Окружение);
	Парсер_Окружение = Окружение;
	Парсер_Переменные = Окружение.Переменные;
	Возврат Окружение;
КонецФункции // ОткрытьОкружение()

Функция ЗакрытьОкружение()
	Перем Окружение;
	Окружение = Парсер_Окружение.ВнешнееОкружение;
	Парсер_Окружение = Окружение;
	Если Окружение <> Неопределено Тогда
		Парсер_Переменные = Окружение.Переменные;
	КонецЕсли;
	Возврат Окружение;
КонецФункции // ЗакрытьОкружение()

Функция Узлы() Экспорт
	Возврат Парсер_Узлы;
КонецФункции

Функция Токенизировать(Исходник) Экспорт
	Перем ПоследнийТокен;
	
	Парсер_Исходник = Исходник;
	Парсер_ТекущаяПозиция = 0;
	Парсер_НомерТекущейСтроки = 1;
	Парсер_ПозицияНачалаТокена = 0;
	Парсер_ПозицияТекущейСтроки = 0;
	Парсер_ДлинаИсходника = СтрДлина(Исходник);
	Парсер_Литерал = "";
	Парсер_Символ = Неопределено;
	Парсер_Ошибки.Очистить();
	Парсер_Токены.Очистить();
	Парсер_ИндексТокена = 0;
	Парсер_ДанныеТекущегоТокена = Парсер_Токены.Добавить();
	Парсер_ДанныеТекущегоТокена.Токен = Токены.НачалоТекста;
	Парсер_Замены.Очистить();
	
	Пока СледующийТокен() <> Токены.КонецТекста Цикл
	КонецЦикла;
	
	ПоследнийТокен = Парсер_Токены[Парсер_Токены.Количество() - 1];
	ПоследнийТокен.Длина = 0;
	
	Возврат Парсер_Токены;
	
КонецФункции

Функция ТаблицаТокенов() Экспорт
	Возврат Парсер_Токены;
КонецФункции

// Служебный метод. Позволяет установить таблицу токенов напрямую без вызова Разобрать().
// Это необходимо делать перед вызовом Посетить() при обработке кэшированных АСД,
// чтобы плагины и бакенды могли получить таблицу токенов из парсера.
Процедура УстановитьТаблицуТокенов(ТаблицаТокенов) Экспорт
	Парсер_Токены = ТаблицаТокенов;
КонецПроцедуры

Функция ТаблицаЗамен() Экспорт
	Возврат Парсер_Замены; 
КонецФункции

Функция ВыполнитьЗамены() Экспорт
	Перем Результат, ПозицияНачала, Индекс, Замена;
	
	Если Парсер_Замены.Количество() = 0 Тогда
		Возврат Неопределено;   
	КонецЕсли;
	
	Результат = Новый Массив;
	
	Парсер_Замены.Сортировать("Позиция");
	
	ПозицияНачала = 1;
	
	Для Индекс = 0 По Парсер_Замены.Количество() - 1 Цикл
		
		Замена = Парсер_Замены[Индекс];
		
		Если Замена.Позиция < ПозицияНачала Тогда
			КодОшибки = 19;
			Ошибка = Парсер_Ошибки.Добавить();
			Ошибка.Источник = "ПарсерВстроенногоЯзыка";
			Ошибка.Код = КодОшибки;
			Ошибка.Текст = СтрШаблон(Ошибки[КодОшибки] + ": `%1`", Замена.Текст);
			Ошибка.ПозицияНачала = Замена.Позиция;
			Ошибка.ПозицияКонца = Замена.Позиция + Замена.Длина;
			Продолжить;
		КонецЕсли;
		
		Результат.Добавить(Сред(Парсер_Исходник, ПозицияНачала, Замена.Позиция - ПозицияНачала));
		Результат.Добавить(Замена.Текст);
		
		ПозицияНачала = Замена.Позиция + Замена.Длина;
		
	КонецЦикла;
	
	Результат.Добавить(Сред(Парсер_Исходник, ПозицияНачала));
	
	Возврат СтрСоединить(Результат);
	
КонецФункции

Функция Разобрать(Исходник, ВнешнееОкружение = Неопределено) Экспорт
	Перем Объявления, Переменные, ОбъявлениеАвтоПеременной, ЭлементОкружения, Операторы, Модуль, ТочкиВызова, ИндексТокена, ПоследнийТокен;
	
	Парсер_Исходник = Исходник;
	Парсер_ТекущаяПозиция = 0;
	Парсер_НомерТекущейСтроки = 1;
	Парсер_ПозицияТекущейСтроки = 0;
	Парсер_ПозицияНачалаТокена = 0;
	Парсер_Неизвестные = Новый Структура;
	Парсер_ТочкиВызова = Новый Соответствие;
	Парсер_ЭтоФункция = Ложь;
	Парсер_ЭтоАсинх = Ложь;
	Парсер_ПеременныеРазрешены = Истина;
	Парсер_Интерфейс = Новый Массив;
	Парсер_ДлинаИсходника = СтрДлина(Исходник);
	Парсер_Литерал = "";
	Парсер_Символ = Неопределено;
	Парсер_Ошибки.Очистить();
	Парсер_Токены.Очистить();
	Парсер_ИндексТокена = 0;
	Парсер_ДанныеТекущегоТокена = Парсер_Токены.Добавить();
	Парсер_ДанныеТекущегоТокена.Токен = Токены.НачалоТекста;
	Парсер_Замены.Очистить(); 
	
	Парсер_Окружение = ВнешнееОкружение;
	ОткрытьОкружение();
	Парсер_Методы = Парсер_Окружение.Методы;
	СледующийТокен();
	Переменные = Новый Массив;
	Объявления = РазобратьОбъявленияМодуля(Переменные);
	Операторы = РазобратьОператоры();
	Для Каждого ОбъявлениеАвтоПеременной Из Парсер_Окружение.АвтоПеременные Цикл
		Переменные.Добавить(ОбъявлениеАвтоПеременной);
	КонецЦикла;
	Модуль = Парсер_Узлы.Модуль.Добавить();
	Модуль.Тип = Типы.Модуль;
	Модуль.Объявления = Объявления;
	Модуль.Переменные = Переменные;
	Модуль.Операторы = Операторы;
	Модуль.Интерфейс = Парсер_Интерфейс;
	Если СтрогийРежим Тогда
		Для Каждого ЭлементОкружения Из Парсер_Неизвестные Цикл
			ТочкиВызова = Парсер_ТочкиВызова[ЭлементОкружения.Значение];
			Для Каждого ИндексТокена Из ТочкиВызова Цикл
				Ошибка(6, ЭлементОкружения.Ключ, Ложь, ИндексТокена);
			КонецЦикла;
		КонецЦикла;
	КонецЕсли;
	Ожидать(Токены.КонецТекста);
	ЗакрытьОкружение();
	
	ПоследнийТокен = Парсер_Токены[Парсер_Токены.Количество() - 1];
	ПоследнийТокен.Длина = 0;
	
	Парсер_Неизвестные = Неопределено;
	Парсер_Методы = Неопределено;
	Парсер_СписокДиректив = Неопределено;
	Парсер_СписокАннотаций = Неопределено;
	Парсер_Интерфейс = Неопределено;
	Парсер_Окружение = Неопределено;
	Парсер_Переменные = Неопределено;
	
	Возврат Модуль;
КонецФункции // Разобрать()

Функция ТаблицаОшибок() Экспорт
	Возврат Парсер_Ошибки;
КонецФункции

// Служебный метод. Позволяет установить таблицу ошибок напрямую без вызова Разобрать().
// Это необходимо делать перед вызовом Посетить() при обработке кэшированных АСД,
// чтобы плагины и бакенды могли получить таблицу ошибок из парсера.
Процедура УстановитьТаблицуОшибок(ТаблицаОшибок) Экспорт
	Парсер_Ошибки = ТаблицаОшибок;
КонецПроцедуры

Функция Исходник() Экспорт
	Возврат Парсер_Исходник;
КонецФункции

// Служебный метод. Позволяет установить исходник напрямую без вызова Разобрать().
// Это необходимо делать перед вызовом Посетить() при обработке кэшированных АСД,
// чтобы плагины и бакенды могли получить исходник из парсера.
Процедура УстановитьИсходник(Исходник) Экспорт
	Парсер_Исходник = Исходник;
КонецПроцедуры

#Область РазборВыражений

Функция РазобратьВыражение()
	Перем Выражение, Операция, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Выражение = РазобратьВыражениеИ();
	Пока Парсер_Токен = Токены.Или Цикл
		Операция = Парсер_ДанныеТекущегоТокена;
		СледующийТокен();
		ЛевыйОперанд = Выражение;
		Выражение = Парсер_Узлы.ВыражениеБинарное.Добавить();
		Выражение.Тип = Типы.ВыражениеБинарное;
		Выражение.ЛевыйОперанд = ЛевыйОперанд;
		Выражение.Операция = Операция;
		Выражение.ПравыйОперанд = РазобратьВыражениеИ();
		Выражение.Начало = Начало;
		Выражение.Конец = Парсер_ДанныеПредыдущегоТокена;
	КонецЦикла;
	Возврат Выражение;
КонецФункции // РазобратьВыражение()

Функция РазобратьВыражениеИ()
	Перем Выражение, Операция, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Выражение = РазобратьВыражениеНе();
	Пока Парсер_Токен = Токены.И Цикл
		Операция = Парсер_ДанныеТекущегоТокена;
		СледующийТокен();
		ЛевыйОперанд = Выражение;
		Выражение = Парсер_Узлы.ВыражениеБинарное.Добавить();
		Выражение.Тип = Типы.ВыражениеБинарное;
		Выражение.ЛевыйОперанд = ЛевыйОперанд;
		Выражение.Операция = Операция;
		Выражение.ПравыйОперанд = РазобратьВыражениеНе();
		Выражение.Начало = Начало;
		Выражение.Конец = Парсер_ДанныеПредыдущегоТокена;
	КонецЦикла;
	Возврат Выражение;
КонецФункции // РазобратьВыражениеИ()

Функция РазобратьВыражениеНе()
	Перем Выражение, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Если Парсер_Токен = Токены.Не Тогда
		СледующийТокен();
		Выражение = Парсер_Узлы.ВыражениеНе.Добавить();
		Выражение.Тип = Типы.ВыражениеНе;
		Выражение.Выражение = РазобратьВыражениеОтношения();
		Выражение.Начало = Начало;
		Выражение.Конец = Парсер_ДанныеПредыдущегоТокена;
	Иначе
		Выражение = РазобратьВыражениеОтношения();
	КонецЕсли;
	Возврат Выражение;
КонецФункции // РазобратьВыражениеНе()

Функция РазобратьВыражениеОтношения()
	Перем Выражение, Операция, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Выражение = РазобратьВыражениеАддитивное();
	Пока ОперацииСравнения.Найти(Парсер_Токен) <> Неопределено Цикл
		Операция = Парсер_ДанныеТекущегоТокена;
		СледующийТокен();
		ЛевыйОперанд = Выражение;
		Выражение = Парсер_Узлы.ВыражениеБинарное.Добавить();
		Выражение.Тип = Типы.ВыражениеБинарное;
		Выражение.ЛевыйОперанд = ЛевыйОперанд;
		Выражение.Операция = Операция;
		Выражение.ПравыйОперанд = РазобратьВыражениеАддитивное();
		Выражение.Начало = Начало;
		Выражение.Конец = Парсер_ДанныеПредыдущегоТокена;
	КонецЦикла;
	Возврат Выражение;
КонецФункции // РазобратьВыражениеОтношения()

Функция РазобратьВыражениеАддитивное()
	Перем Выражение, Операция, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Выражение = РазобратьВыражениеМультипликативное();
	Пока ОперацииАддитивные.Найти(Парсер_Токен) <> Неопределено Цикл
		Операция = Парсер_ДанныеТекущегоТокена;
		СледующийТокен();
		ЛевыйОперанд = Выражение;
		Выражение = Парсер_Узлы.ВыражениеБинарное.Добавить();
		Выражение.Тип = Типы.ВыражениеБинарное;
		Выражение.ЛевыйОперанд = ЛевыйОперанд;
		Выражение.Операция = Операция;
		Выражение.ПравыйОперанд = РазобратьВыражениеМультипликативное();
		Выражение.Начало = Начало;
		Выражение.Конец = Парсер_ДанныеПредыдущегоТокена;
	КонецЦикла;
	Возврат Выражение;
КонецФункции // РазобратьВыражениеАддитивное()

Функция РазобратьВыражениеМультипликативное()
	Перем Выражение, Операция, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Выражение = РазобратьВыражениеУнарное();
	Пока ОперацииМультипликативные.Найти(Парсер_Токен) <> Неопределено Цикл
		Операция = Парсер_ДанныеТекущегоТокена;
		СледующийТокен();
		ЛевыйОперанд = Выражение;
		Выражение = Парсер_Узлы.ВыражениеБинарное.Добавить();
		Выражение.Тип = Типы.ВыражениеБинарное;
		Выражение.ЛевыйОперанд = ЛевыйОперанд;
		Выражение.Операция = Операция;
		Выражение.ПравыйОперанд = РазобратьВыражениеУнарное();
		Выражение.Начало = Начало;
		Выражение.Конец = Парсер_ДанныеПредыдущегоТокена;
	КонецЦикла;
	Возврат Выражение;
КонецФункции // РазобратьВыражениеМультипликативное()

Функция РазобратьВыражениеУнарное()
	Перем Операция, Выражение, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Операция = Парсер_ДанныеТекущегоТокена;
	Если ОперацииАддитивные.Найти(Парсер_Токен) <> Неопределено Тогда
		СледующийТокен();
		Выражение = Парсер_Узлы.ВыражениеУнарное.Добавить();
		Выражение.Тип = Типы.ВыражениеУнарное;
		Выражение.Операция = Операция;
		Выражение.Операнд = РазобратьОперанд();
		Выражение.Начало = Начало;
		Выражение.Конец = Парсер_ДанныеПредыдущегоТокена;
	ИначеЕсли Парсер_Токен = Токены.КонецТекста Тогда
		Выражение = Неопределено;
	Иначе
		Выражение = РазобратьОперанд();
	КонецЕсли;
	Возврат Выражение;
КонецФункции // РазобратьВыражениеУнарное()

Функция РазобратьОперанд()
	Перем Операнд;
	Если Парсер_Токен = Токены.Строка Или Парсер_Токен = Токены.НачалоСтроки Тогда
		Операнд = РазобратьВыражениеСтроковое();
	ИначеЕсли ЛитералКромеСтроки.Найти(Парсер_Токен) <> Неопределено Тогда
		Операнд = Парсер_Узлы.ВыражениеЛитерал.Добавить();
		Операнд.Тип = Типы.ВыражениеЛитерал;
		Операнд.Вид = Парсер_Токен;
		Операнд.Значение = Парсер_Значение;
		Операнд.Начало = Парсер_ДанныеТекущегоТокена;
		Операнд.Конец = Парсер_ДанныеТекущегоТокена;
		СледующийТокен();
	ИначеЕсли Парсер_Токен = Токены.Идентификатор Тогда
		Операнд = РазобратьВыражениеИдентификатор();
	ИначеЕсли Парсер_Токен = Токены.ЛеваяКруглаяСкобка Тогда
		Операнд = РазобратьВыражениеСкобочное();
	ИначеЕсли Парсер_Токен = Токены.Новый Тогда
		Операнд = РазобратьВыражениеНовый();
	ИначеЕсли Парсер_Токен = Токены.ЗнакВопроса Тогда
		Операнд = РазобратьВыражениеТернарное();
	ИначеЕсли Парсер_Токен = Токены.Ждать Тогда
		Операнд = РазобратьВыражениеОператорЖдать();
	Иначе
		Ошибка(7, Неопределено, Истина, Парсер_ДанныеТекущегоТокена);
	КонецЕсли;
	Возврат Операнд;
КонецФункции // РазобратьОперанд()

Функция РазобратьВыражениеСтроковое()
	Перем СписокВыражений, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СписокВыражений = Новый Массив;
	Пока Истина Цикл
		Если Парсер_Токен = Токены.Строка Тогда
			Узел = Парсер_Узлы.ВыражениеЛитерал.Добавить();
			Узел.Тип = Типы.ВыражениеЛитерал;
			Узел.Вид = Парсер_Токен;
			Узел.Значение = Парсер_Значение;
			Узел.Начало = Парсер_ДанныеТекущегоТокена;
			Узел.Конец = Парсер_ДанныеТекущегоТокена;;
			СписокВыражений.Добавить(Узел);
			СледующийТокен();
			Пока Парсер_Токен = Токены.Строка Цикл
				Узел = Парсер_Узлы.ВыражениеЛитерал.Добавить();
				Узел.Тип = Типы.ВыражениеЛитерал;
				Узел.Вид = Парсер_Токен;
				Узел.Значение = Парсер_Значение;
				Узел.Начало = Парсер_ДанныеТекущегоТокена;
				Узел.Конец = Парсер_ДанныеТекущегоТокена;;
				СписокВыражений.Добавить(Узел);
				СледующийТокен();
			КонецЦикла;
		ИначеЕсли Парсер_Токен = Токены.НачалоСтроки Тогда
			Узел = Парсер_Узлы.ВыражениеЛитерал.Добавить();
			Узел.Тип = Типы.ВыражениеЛитерал;
			Узел.Вид = Парсер_Токен;
			Узел.Значение = Парсер_Значение;
			Узел.Начало = Парсер_ДанныеТекущегоТокена;
			Узел.Конец = Парсер_ДанныеТекущегоТокена;;
			СписокВыражений.Добавить(Узел);
			СледующийТокен();
			Пока Парсер_Токен = Токены.ПродолжениеСтроки Цикл
				Узел = Парсер_Узлы.ВыражениеЛитерал.Добавить();
				Узел.Тип = Типы.ВыражениеЛитерал;
				Узел.Вид = Парсер_Токен;
				Узел.Значение = Парсер_Значение;
				Узел.Начало = Парсер_ДанныеТекущегоТокена;
				Узел.Конец = Парсер_ДанныеТекущегоТокена;;
				СписокВыражений.Добавить(Узел);
				СледующийТокен();
			КонецЦикла;
			Если Парсер_Токен <> Токены.ОкончаниеСтроки Тогда
				Ошибка(1, """", Истина, Парсер_ДанныеТекущегоТокена);
			КонецЕсли;
			Узел = Парсер_Узлы.ВыражениеЛитерал.Добавить();
			Узел.Тип = Типы.ВыражениеЛитерал;
			Узел.Вид = Парсер_Токен;
			Узел.Значение = Парсер_Значение;
			Узел.Начало = Парсер_ДанныеТекущегоТокена;
			Узел.Конец = Парсер_ДанныеТекущегоТокена;;
			СписокВыражений.Добавить(Узел);
			СледующийТокен();
		Иначе
			Прервать;
		КонецЕсли;
	КонецЦикла;
	Узел = Парсер_Узлы.ВыражениеСтроковое.Добавить();
	Узел.Тип = Типы.ВыражениеСтроковое;
	Узел.Элементы = СписокВыражений;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьВыражениеСтроковое()

Функция РазобратьВыражениеНовый()
	Перем Имя, Аргументы, Хвост, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Если Парсер_Токен = Токены.Идентификатор Тогда
		Имя = Парсер_Литерал;
		Аргументы = ПустойМассив;
		СледующийТокен();
	КонецЕсли;
	Хвост = ПустойМассив;
	Если Парсер_Токен = Токены.ЛеваяКруглаяСкобка Тогда
		СледующийТокен();
		Если Парсер_Токен <> Токены.ПраваяКруглаяСкобка Тогда
			Аргументы = РазобратьАргументы();
			Ожидать(Токены.ПраваяКруглаяСкобка);
		КонецЕсли;
		СледующийТокен();
		Если Парсер_Токен = Токены.Точка Тогда
			Хвост = РазобратьХвост();
		КонецЕсли;
	КонецЕсли;
	Если Имя = Неопределено Тогда
		Если Аргументы = Неопределено Тогда
			Ошибка(8, Неопределено, Истина, Парсер_ДанныеТекущегоТокена);
		ИначеЕсли Аргументы.Количество() > 2 Тогда
			Ошибка(9, Неопределено, Истина, Начало, Парсер_ДанныеТекущегоТокена);
		КонецЕсли;
	КонецЕсли;
	Узел = Парсер_Узлы.ВыражениеНовый.Добавить();
	Узел.Тип = Типы.ВыражениеНовый;
	Узел.Имя = Имя;
	Узел.Аргументы = Аргументы;
	Узел.Хвост = Хвост;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьВыражениеНовый()

Функция РазобратьВыражениеИдентификатор(Знач НоваяПеременнаяРазрешена = Ложь, НоваяПеременная = Неопределено, ЭтоВызов = Неопределено)
	Перем Имя, ЭлементОкружения, Хвост, Аргументы, НачалоАвтоПеременной, ТочкиВызова, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Имя = Парсер_Литерал;
	НачалоАвтоПеременной = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Если Парсер_Токен = Токены.ЛеваяКруглаяСкобка Тогда
		Если СледующийТокен() = Токены.ПраваяКруглаяСкобка Тогда
			Аргументы = ПустойМассив;
		Иначе
			Аргументы = РазобратьАргументы();
		КонецЕсли;
		Ожидать(Токены.ПраваяКруглаяСкобка);
		СледующийТокен();
		ЭлементОкружения = НайтиМетод(Имя);
		Если ЭлементОкружения = Неопределено Тогда
			Если Парсер_Неизвестные.Свойство(Имя, ЭлементОкружения) Тогда
				ТочкиВызова = Парсер_ТочкиВызова[ЭлементОкружения];
				ТочкиВызова.Добавить(НачалоАвтоПеременной);
			Иначе
				ЭлементОкружения = Парсер_Узлы.ЭлементОкружения.Добавить();
				ЭлементОкружения.Тип = Типы.ЭлементОкружения;
				ЭлементОкружения.Имя = Имя;
				ЭлементОкружения.Объявление = Неопределено;
				Парсер_Неизвестные.Вставить(Имя, ЭлементОкружения);
				ТочкиВызова = Новый Массив;
				ТочкиВызова.Добавить(НачалоАвтоПеременной);
				Парсер_ТочкиВызова[ЭлементОкружения] = ТочкиВызова;
			КонецЕсли;
		КонецЕсли;
		ЭтоВызов = Истина;
		Хвост = РазобратьХвост(ЭтоВызов);
	Иначе
		ЭтоВызов = Ложь;
		Хвост = РазобратьХвост(ЭтоВызов);
		Если Хвост.Количество() > 0 Тогда
			НоваяПеременнаяРазрешена = Ложь;
		КонецЕсли;
		ЭлементОкружения = НайтиЭлементОкружения(Имя);
		Если ЭлементОкружения = Неопределено Тогда
			Если НоваяПеременнаяРазрешена Тогда
				ЭлементОкружения = Парсер_Узлы.ЭлементОкружения.Добавить();
				ЭлементОкружения.Тип = Типы.ЭлементОкружения;
				ЭлементОкружения.Имя = Имя;
				ЭлементОкружения.Объявление = Парсер_Узлы.ОбъявлениеАвтоПеременной.Добавить();
				ЭлементОкружения.Объявление.Тип = Типы.ОбъявлениеАвтоПеременной;
				ЭлементОкружения.Объявление.Имя = Имя;
				ЭлементОкружения.Объявление.Начало = НачалоАвтоПеременной;
				ЭлементОкружения.Объявление.Конец = НачалоАвтоПеременной;;
				НоваяПеременная = ЭлементОкружения;
			Иначе
				ЭлементОкружения = Парсер_Узлы.ЭлементОкружения.Добавить();
				ЭлементОкружения.Тип = Типы.ЭлементОкружения;
				ЭлементОкружения.Имя = Имя;
				ЭлементОкружения.Объявление = Неопределено;
				Если СтрогийРежим Тогда
					Ошибка(10, Имя, Ложь, Начало);
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	Узел = Парсер_Узлы.ВыражениеИдентификатор.Добавить();
	Узел.Тип = Типы.ВыражениеИдентификатор;
	Узел.Голова = ЭлементОкружения;
	Узел.Хвост = Хвост;
	Узел.Аргументы = Аргументы;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьВыражениеИдентификатор()

Функция РазобратьХвост(Вызов = Неопределено)
	Перем Хвост, Имя, Аргументы, Выражение, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Хвост = Новый Массив;
	Пока Истина Цикл
		Если Парсер_Токен = Токены.Точка Тогда
			СледующийТокен();
			Если КартаБуквЦифр[Лев(Парсер_Литерал, 1)] <> Буква Или Не КлючевыеСлова.Свойство(Парсер_Литерал) Тогда
				Ожидать(Токены.Идентификатор);
			КонецЕсли;
			Имя = Парсер_Литерал;
			Если СледующийТокен() = Токены.ЛеваяКруглаяСкобка Тогда
				Если СледующийТокен() = Токены.ПраваяКруглаяСкобка Тогда
					Аргументы = ПустойМассив;
				Иначе
					Аргументы = РазобратьАргументы();
				КонецЕсли;
				Ожидать(Токены.ПраваяКруглаяСкобка);
				СледующийТокен();
				Вызов = Истина;
			Иначе
				Аргументы = Неопределено;
				Вызов = Ложь;
			КонецЕсли;
			Узел = Парсер_Узлы.ВыражениеПоле.Добавить();
			Узел.Тип = Типы.ВыражениеПоле;
			Узел.Имя = Имя;
			Узел.Аргументы = Аргументы;
			Узел.Начало = Начало;
			Узел.Конец = Парсер_ДанныеПредыдущегоТокена;;
			Хвост.Добавить(Узел);
		ИначеЕсли Парсер_Токен = Токены.ЛеваяКвадратнаяСкобка Тогда
			Вызов = Ложь;
			Если СледующийТокен() = Токены.ПраваяКвадратнаяСкобка Тогда
				Ошибка(11, Неопределено, Истина, Парсер_ДанныеТекущегоТокена);
			КонецЕсли;
			Выражение = РазобратьВыражение();
			Ожидать(Токены.ПраваяКвадратнаяСкобка);
			СледующийТокен();
			Узел = Парсер_Узлы.ВыражениеИндекс.Добавить();
			Узел.Тип = Типы.ВыражениеИндекс;
			Узел.Выражение = Выражение;
			Узел.Начало = Начало;
			Узел.Конец = Парсер_ДанныеПредыдущегоТокена;;
			Хвост.Добавить(Узел);
		Иначе
			Прервать;
		КонецЕсли;
	КонецЦикла;
	Возврат Хвост;
КонецФункции // РазобратьХвост()

Функция РазобратьАргументы()
	Перем СписокВыражений;
	СписокВыражений = Новый Массив;
	Пока Истина Цикл
		Если ТокеныНачалаВыражения.Найти(Парсер_Токен) <> Неопределено Тогда
			СписокВыражений.Добавить(РазобратьВыражение());
		Иначе
			СписокВыражений.Добавить(Неопределено);
		КонецЕсли;
		Если Парсер_Токен = Токены.Запятая Тогда
			СледующийТокен();
		Иначе
			Прервать;
		КонецЕсли;
	КонецЦикла;
	Возврат СписокВыражений;
КонецФункции // РазобратьАргументы()

Функция РазобратьВыражениеТернарное()
	Перем Выражение, ТогдаОператоры, ИначеОператоры, Хвост, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Ожидать(Токены.ЛеваяКруглаяСкобка);
	СледующийТокен();
	Выражение = РазобратьВыражение();
	Ожидать(Токены.Запятая);
	СледующийТокен();
	ТогдаОператоры = РазобратьВыражение();
	Ожидать(Токены.Запятая);
	СледующийТокен();
	ИначеОператоры = РазобратьВыражение();
	Ожидать(Токены.ПраваяКруглаяСкобка);
	Если СледующийТокен() = Токены.Точка Тогда
		Хвост = РазобратьХвост();
	Иначе
		Хвост = ПустойМассив;
	КонецЕсли;
	Узел = Парсер_Узлы.ВыражениеТернарное.Добавить();
	Узел.Тип = Типы.ВыражениеТернарное;
	Узел.Выражение = Выражение;
	Узел.Тогда = ТогдаОператоры;
	Узел.Иначе = ИначеОператоры;
	Узел.Хвост = Хвост;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьВыражениеТернарное()

Функция РазобратьВыражениеСкобочное()
	Перем Выражение, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Выражение = РазобратьВыражение();
	Ожидать(Токены.ПраваяКруглаяСкобка);
	СледующийТокен();
	Узел = Парсер_Узлы.ВыражениеСкобочное.Добавить();
	Узел.Тип = Типы.ВыражениеСкобочное;
	Узел.Выражение = Выражение;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьВыражениеСкобочное()

Функция РазобратьВыражениеОператорЖдать()
	Перем Операция, Выражение, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	
	Если Не Парсер_ЭтоАсинх Тогда
		Ошибка(21, Неопределено, Истина);
	КонецЕсли;
	
	СледующийТокен();
	Выражение = Парсер_Узлы.ВыражениеЖдать.Добавить();
	Выражение.Тип = Типы.ВыражениеЖдать;
	Выражение.Выражение = РазобратьОперанд();
	Выражение.Начало = Начало;
	Выражение.Конец = Парсер_ДанныеПредыдущегоТокена;
	
	Возврат Выражение;
КонецФункции // РазобратьВыражениеУнарное()

#КонецОбласти // РазборВыражений

#Область РазборОбъявлений

Функция РазобратьОбъявленияМодуля(Переменные)
	Перем Объявления, ОбъявлениеДирективы;
	Объявления = Новый Массив;
	Пока Истина Цикл
		Парсер_СписокДиректив = Новый Массив;
		Парсер_СписокАннотаций = Новый Массив;
		Пока Истина Цикл
			Если Парсер_Токен = Токены.Директива Тогда
				ОбъявлениеДирективы = Парсер_Узлы.ОбъявлениеДирективы.Добавить();
				ОбъявлениеДирективы.Тип = Типы.ОбъявлениеДирективы;
				ОбъявлениеДирективы.Директива = Директивы[Парсер_Литерал];
				ОбъявлениеДирективы.Начало = Парсер_ДанныеТекущегоТокена;
				ОбъявлениеДирективы.Конец = Парсер_ДанныеТекущегоТокена;
				Парсер_СписокДиректив.Добавить(ОбъявлениеДирективы);
				СледующийТокен();
			ИначеЕсли Парсер_Токен = Токены.Аннотация Тогда
				Аннотация = Аннотации[Парсер_Литерал];
				НачалоАннотации = Парсер_ДанныеТекущегоТокена;
				СледующийТокен();
				Ожидать(Токены.ЛеваяКруглаяСкобка);
				СледующийТокен();
				Ожидать(Токены.Строка);
				ИмяМетода = Парсер_Значение;
				СледующийТокен();
				Ожидать(Токены.ПраваяКруглаяСкобка);
				ОбъявлениеАннотации = Парсер_Узлы.ОбъявлениеАннотации.Добавить();
				ОбъявлениеАннотации.Тип = Типы.ОбъявлениеАннотации;
				ОбъявлениеАннотации.Аннотация = Аннотация;
				ОбъявлениеАннотации.ИмяМетода = ИмяМетода;
				ОбъявлениеАннотации.Начало = НачалоАннотации;
				ОбъявлениеАннотации.Конец = Парсер_ДанныеТекущегоТокена;
				Парсер_СписокАннотаций.Добавить(ОбъявлениеАннотации);
				СледующийТокен();
			Иначе
				Прервать;
			КонецЕсли; 
		КонецЦикла;
		Если Парсер_Токен = Токены.Перем И Парсер_ПеременныеРазрешены Тогда
			Объявления.Добавить(РазобратьОбъявлениеСпискаПеременныхМодуля(Переменные));
		ИначеЕсли Парсер_Токен = Токены.Асинх Тогда
			Парсер_ЭтоАсинх = Истина;
			Объявления.Добавить(РазобратьОбъявлениеМетода());
			Парсер_ЭтоФункция = Ложь;
			Парсер_ПеременныеРазрешены = Ложь;
			Парсер_ЭтоАсинх = Ложь;
		ИначеЕсли Парсер_Токен = Токены.Функция Тогда
			Парсер_ЭтоФункция = Истина;
			Объявления.Добавить(РазобратьОбъявлениеМетода());
			Парсер_ЭтоФункция = Ложь;
			Парсер_ПеременныеРазрешены = Ложь;
		ИначеЕсли Парсер_Токен = Токены.Процедура Тогда
			Объявления.Добавить(РазобратьОбъявлениеМетода());
			Парсер_ПеременныеРазрешены = Ложь;
		ИначеЕсли Парсер_Токен = Токены._Область Тогда
			Объявления.Добавить(РазобратьИнструкциюПрепроцессораОбласть());
			СледующийТокен();
		ИначеЕсли Парсер_Токен = Токены._КонецОбласти Тогда
			Объявления.Добавить(РазобратьИнструкциюПрепроцессораКонецОбласти());
			СледующийТокен();
		ИначеЕсли Парсер_Токен = Токены._Если Тогда
			Объявления.Добавить(РазобратьИнструкциюПрепроцессораЕсли());
			СледующийТокен();
		ИначеЕсли Парсер_Токен = Токены._ИначеЕсли Тогда
			Объявления.Добавить(РазобратьИнструкциюПрепроцессораИначеЕсли());
			СледующийТокен();
		ИначеЕсли Парсер_Токен = Токены._Иначе Тогда
			Объявления.Добавить(РазобратьИнструкциюПрепроцессораИначе());
			СледующийТокен();
		ИначеЕсли Парсер_Токен = Токены._КонецЕсли Тогда
			Объявления.Добавить(РазобратьИнструкциюПрепроцессораКонецЕсли());
			СледующийТокен();
		ИначеЕсли Парсер_Токен = Токены._Использовать Тогда
			Объявления.Добавить(РазобратьИнструкциюПрепроцессораИспользовать());
			СледующийТокен();	
		Иначе
			Прервать;
		КонецЕсли;
	КонецЦикла;
	Возврат Объявления;
КонецФункции // РазобратьОбъявленияМодуля()

Функция РазобратьОбъявлениеСпискаПеременныхМодуля(Переменные)
	Перем ОбъявленияПеременных, ОбъявлениеПеременной, Объявление, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	ОбъявленияПеременных = Новый Массив;
	ОбъявлениеПеременной = РазобратьОбъявлениеПеременнойМодуля(); 
	ОбъявленияПеременных.Добавить(ОбъявлениеПеременной);
	Переменные.Добавить(ОбъявлениеПеременной);
	Пока Парсер_Токен = Токены.Запятая Цикл
		СледующийТокен();
		ОбъявлениеПеременной = РазобратьОбъявлениеПеременнойМодуля();
		ОбъявленияПеременных.Добавить(ОбъявлениеПеременной);
		Переменные.Добавить(ОбъявлениеПеременной);
	КонецЦикла;
	Объявление = Парсер_Узлы.ОбъявлениеСпискаПеременныхМодуля.Добавить();
	Объявление.Тип = Типы.ОбъявлениеСпискаПеременныхМодуля;
	Объявление.Директивы = Парсер_СписокДиректив;
	Объявление.Объявления = ОбъявленияПеременных;
	Объявление.Начало = Начало;
	Объявление.Конец = Парсер_ДанныеПредыдущегоТокена;
	Ожидать(Токены.ТочкаСЗапятой);
	СледующийТокен();
	Пока Парсер_Токен = Токены.ТочкаСЗапятой Цикл
		СледующийТокен();
	КонецЦикла;
	Возврат Объявление;
КонецФункции // РазобратьОбъявлениеСпискаПеременныхМодуля()

Функция РазобратьОбъявлениеПеременнойМодуля()
	Перем Имя, ОбъявлениеПеременнойМодуля, ЭлементОкружения, ЕстьЭкспорт, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Ожидать(Токены.Идентификатор);
	Имя = Парсер_Литерал;
	Если СледующийТокен() = Токены.Экспорт Тогда
		ЕстьЭкспорт = Истина;
		СледующийТокен();
	Иначе
		ЕстьЭкспорт = Ложь;
	КонецЕсли;
	ОбъявлениеПеременнойМодуля = Парсер_Узлы.ОбъявлениеПеременнойМодуля.Добавить();
	ОбъявлениеПеременнойМодуля.Тип = Типы.ОбъявлениеПеременнойМодуля;
	ОбъявлениеПеременнойМодуля.Имя = Имя;
	ОбъявлениеПеременнойМодуля.Директивы = Парсер_СписокДиректив;
	ОбъявлениеПеременнойМодуля.Экспорт = ЕстьЭкспорт;
	ОбъявлениеПеременнойМодуля.Начало = Начало;
	ОбъявлениеПеременнойМодуля.Конец = Парсер_ДанныеПредыдущегоТокена;
	Если Парсер_Переменные.Свойство(Имя) Тогда
		Ошибка(12, Имя, СтрогийРежим, Начало);
	КонецЕсли;
	ЭлементОкружения = Парсер_Узлы.ЭлементОкружения.Добавить();
	ЭлементОкружения.Тип = Типы.ЭлементОкружения;
	ЭлементОкружения.Имя = Имя;
	ЭлементОкружения.Объявление = ОбъявлениеПеременнойМодуля;
	Парсер_Переменные.Вставить(Имя, ЭлементОкружения);
	Если ЕстьЭкспорт Тогда
		Парсер_Интерфейс.Добавить(ЭлементОкружения);
	КонецЕсли;
	Возврат ОбъявлениеПеременнойМодуля;
КонецФункции // РазобратьОбъявлениеПеременнойМодуля()

Функция РазобратьОбъявлениеСпискаЛокальныхПеременных(Переменные)
	Перем ОбъявленияПеременных, ОбъявлениеПеременной, Объявление, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	ОбъявленияПеременных = Новый Массив;
	ОбъявлениеПеременной = РазобратьОбъявлениеЛокальнойПеременной(); 
	ОбъявленияПеременных.Добавить(ОбъявлениеПеременной);
	Переменные.Добавить(ОбъявлениеПеременной);
	Пока Парсер_Токен = Токены.Запятая Цикл
		СледующийТокен();
		ОбъявлениеПеременной = РазобратьОбъявлениеЛокальнойПеременной();
		ОбъявленияПеременных.Добавить(ОбъявлениеПеременной);
		Переменные.Добавить(ОбъявлениеПеременной);
	КонецЦикла;
	Объявление = Парсер_Узлы.ОбъявлениеСпискаЛокальныхПеременных.Добавить();
	Объявление.Тип = Типы.ОбъявлениеСпискаЛокальныхПеременных;
	Объявление.Объявления = ОбъявленияПеременных;
	Объявление.Начало = Начало;
	Объявление.Конец = Парсер_ДанныеПредыдущегоТокена;
	Ожидать(Токены.ТочкаСЗапятой);
	СледующийТокен();
	Пока Парсер_Токен = Токены.ТочкаСЗапятой Цикл
		СледующийТокен();
	КонецЦикла;
	Возврат Объявление;
КонецФункции // РазобратьОбъявлениеСпискаЛокальныхПеременных()

Функция РазобратьОбъявлениеЛокальнойПеременной()
	Перем Имя, ОбъявлениеЛокальнойПеременной, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Ожидать(Токены.Идентификатор);
	Имя = Парсер_Литерал;
	ОбъявлениеЛокальнойПеременной = Парсер_Узлы.ОбъявлениеЛокальнойПеременной.Добавить();
	ОбъявлениеЛокальнойПеременной.Тип = Типы.ОбъявлениеЛокальнойПеременной;
	ОбъявлениеЛокальнойПеременной.Имя = Имя;
	ОбъявлениеЛокальнойПеременной.Начало = Начало;
	ОбъявлениеЛокальнойПеременной.Конец = Начало;
	Если Парсер_Переменные.Свойство(Имя) Тогда
		Ошибка(12, Имя, СтрогийРежим, Парсер_ДанныеТекущегоТокена);
	КонецЕсли;
	ЭлементОкружения = Парсер_Узлы.ЭлементОкружения.Добавить();
	ЭлементОкружения.Тип = Типы.ЭлементОкружения;
	ЭлементОкружения.Имя = Имя;
	ЭлементОкружения.Объявление = ОбъявлениеЛокальнойПеременной;;
	Парсер_Переменные.Вставить(Имя, ЭлементОкружения);
	СледующийТокен();
	Возврат ОбъявлениеЛокальнойПеременной;
КонецФункции // РазобратьОбъявлениеЛокальнойПеременной()

Функция РазобратьОбъявлениеМетода()
	Перем Сигнатура, ЭлементОкружения, Имя, Переменные, Параметры, ЕстьЭкспорт, Операторы, Объявления, ОбъявлениеАвтоПеременной, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Если Парсер_Токен = Токены.Асинх Тогда
		СледующийТокен();
	КонецЕсли;
	ЕстьЭкспорт = Ложь;
	СледующийТокен();
	Ожидать(Токены.Идентификатор);
	Имя = Парсер_Литерал;
	СледующийТокен();
	ОткрытьОкружение();
	Параметры = РазобратьПараметры();
	Если Парсер_Токен = Токены.Экспорт Тогда
		ЕстьЭкспорт = Истина;
		СледующийТокен();
	КонецЕсли;
	Если Парсер_ЭтоФункция Тогда
		Сигнатура = Парсер_Узлы.ОбъявлениеСигнатурыФункции.Добавить();
		Сигнатура.Тип = Типы.ОбъявлениеСигнатурыФункции;
		Сигнатура.Имя = Имя;
		Сигнатура.Директивы = Парсер_СписокДиректив;
		Сигнатура.Аннотации = Парсер_СписокАннотаций;
		Сигнатура.Параметры = Параметры;
		Сигнатура.Экспорт = ЕстьЭкспорт;
		Сигнатура.Асинх = Парсер_ЭтоАсинх;
		Сигнатура.Начало = Начало;
		Сигнатура.Конец = Парсер_ДанныеПредыдущегоТокена;
	Иначе
		Сигнатура = Парсер_Узлы.ОбъявлениеСигнатурыПроцедуры.Добавить();
		Сигнатура.Тип = Типы.ОбъявлениеСигнатурыПроцедуры;
		Сигнатура.Имя = Имя;
		Сигнатура.Директивы = Парсер_СписокДиректив;
		Сигнатура.Аннотации = Парсер_СписокАннотаций;
		Сигнатура.Параметры = Параметры;
		Сигнатура.Экспорт = ЕстьЭкспорт;
		Сигнатура.Асинх = Парсер_ЭтоАсинх;
		Сигнатура.Начало = Начало;
		Сигнатура.Конец = Парсер_ДанныеПредыдущегоТокена;
	КонецЕсли;
	Если Парсер_Неизвестные.Свойство(Имя, ЭлементОкружения) Тогда
		Парсер_Неизвестные.Удалить(Имя);
		ЭлементОкружения.Объявление = Сигнатура;
	Иначе
		ЭлементОкружения = Парсер_Узлы.ЭлементОкружения.Добавить();
		ЭлементОкружения.Тип = Типы.ЭлементОкружения;
		ЭлементОкружения.Имя = Имя;
		ЭлементОкружения.Объявление = Сигнатура;
	КонецЕсли;
	Если НайтиМетод(Имя) <> Неопределено Тогда
		Ошибка(13, Имя, СтрогийРежим, Парсер_Токены[Начало.Индекс + 1]);
	КонецЕсли;
	Парсер_Методы.Вставить(Имя, ЭлементОкружения);
	Если ЕстьЭкспорт Тогда
		Парсер_Интерфейс.Добавить(ЭлементОкружения);
	КонецЕсли;
	Объявления = Новый Массив;
	Переменные = Новый Массив;	
	Пока Парсер_Токен = Токены.Перем Цикл
		Объявления.Добавить(РазобратьОбъявлениеСпискаЛокальныхПеременных(Переменные));
	КонецЦикла;
	Операторы = РазобратьОператоры();
	Если Парсер_ЭтоФункция Тогда
		Ожидать(Токены.КонецФункции);
	Иначе
		Ожидать(Токены.КонецПроцедуры);
	КонецЕсли;
	Для Каждого ОбъявлениеАвтоПеременной Из Парсер_Окружение.АвтоПеременные Цикл
		Переменные.Добавить(ОбъявлениеАвтоПеременной);
	КонецЦикла;
	ЗакрытьОкружение();
	СледующийТокен();
	Узел = Парсер_Узлы.ОбъявлениеМетода.Добавить();
	Узел.Тип = Типы.ОбъявлениеМетода;
	Узел.Сигнатура = Сигнатура;
	Узел.Переменные = Переменные;
	Узел.Объявления = Объявления;
	Узел.Операторы = Операторы;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьОбъявлениеМетода()

Функция РазобратьПараметры()
	Перем Параметры;
	Ожидать(Токены.ЛеваяКруглаяСкобка);
	СледующийТокен();
	Если Парсер_Токен = Токены.ПраваяКруглаяСкобка Тогда
		Параметры = ПустойМассив;
	Иначе
		Параметры = Новый Массив;
		Параметры.Добавить(РазобратьОбъявлениеПараметра());
		Пока Парсер_Токен = Токены.Запятая Цикл
			СледующийТокен();
			Параметры.Добавить(РазобратьОбъявлениеПараметра());
		КонецЦикла;
	КонецЕсли;
	Ожидать(Токены.ПраваяКруглаяСкобка);
	СледующийТокен();
	Возврат Параметры;
КонецФункции // РазобратьПараметры()

Функция РазобратьОбъявлениеПараметра()
	Перем Имя, ОбъявлениеПараметра, ПоЗначению, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Если Парсер_Токен = Токены.Знач Тогда
		ПоЗначению = Истина;
		СледующийТокен();
	Иначе
		ПоЗначению = Ложь;
	КонецЕсли;
	Ожидать(Токены.Идентификатор);
	Имя = Парсер_Литерал;
	Если СледующийТокен() = Токены.ЗнакРавно Тогда
		СледующийТокен();
		ОбъявлениеПараметра = Парсер_Узлы.ОбъявлениеПараметра.Добавить();
		ОбъявлениеПараметра.Тип = Типы.ОбъявлениеПараметра;
		ОбъявлениеПараметра.Имя = Имя;
		ОбъявлениеПараметра.ПоЗначению = ПоЗначению;
		ОбъявлениеПараметра.Значение = РазобратьВыражениеУнарное();
		ОбъявлениеПараметра.Начало = Начало;
		ОбъявлениеПараметра.Конец = Парсер_ДанныеПредыдущегоТокена;
	Иначе
		ОбъявлениеПараметра = Парсер_Узлы.ОбъявлениеПараметра.Добавить();
		ОбъявлениеПараметра.Тип = Типы.ОбъявлениеПараметра;
		ОбъявлениеПараметра.Имя = Имя;
		ОбъявлениеПараметра.ПоЗначению = ПоЗначению;
		ОбъявлениеПараметра.Значение = Неопределено;
		ОбъявлениеПараметра.Начало = Начало;
		ОбъявлениеПараметра.Конец = Парсер_ДанныеПредыдущегоТокена;
	КонецЕсли;
	Если Парсер_Переменные.Свойство(Имя) Тогда
		Ошибка(12, Имя, СтрогийРежим, Начало);
	КонецЕсли;
	ЭлементОкружения = Парсер_Узлы.ЭлементОкружения.Добавить();
	ЭлементОкружения.Тип = Типы.ЭлементОкружения;
	ЭлементОкружения.Имя = Имя;
	ЭлементОкружения.Объявление = ОбъявлениеПараметра;;
	Парсер_Переменные.Вставить(Имя, ЭлементОкружения);
	Возврат ОбъявлениеПараметра;
КонецФункции // РазобратьОбъявлениеПараметра()

#КонецОбласти // РазборОбъявлений

#Область РазборОператоров

Функция РазобратьОператоры()
	Перем Операторы, Оператор;
	Операторы = Новый Массив;
	Оператор = РазобратьОператор();
	Если Оператор <> Неопределено Тогда
		Операторы.Добавить(Оператор);
	КонецЕсли;
	Пока Истина Цикл
		Если Парсер_Токен = Токены.ТочкаСЗапятой Тогда
			СледующийТокен();
		ИначеЕсли Лев(Парсер_Токен, 1) <> "_" Тогда // если не препроцессор
			Прервать;
		КонецЕсли;
		Оператор = РазобратьОператор();
		Если Оператор <> Неопределено Тогда
			Операторы.Добавить(Оператор);
		КонецЕсли;
	КонецЦикла;
	Возврат Операторы;
КонецФункции // РазобратьОператоры()

Функция РазобратьОператор()
	Перем Оператор;
	Если Парсер_Токен = Токены.Идентификатор Тогда
		Оператор = РазобратьОператорПрисваиванияИлиВызоваПроцедуры();
	ИначеЕсли Парсер_Токен = Токены.Если Тогда
		Оператор = РазобратьОператорЕсли();
	ИначеЕсли Парсер_Токен = Токены.Попытка Тогда
		Оператор = РазобратьОператорПопытка();
	ИначеЕсли Парсер_Токен = Токены.Пока Тогда
		Оператор = РазобратьОператорПока();
	ИначеЕсли Парсер_Токен = Токены.Для Тогда
		Если СледующийТокен() = Токены.Каждого Тогда
			Оператор = РазобратьОператорДляКаждого();
		Иначе
			Оператор = РазобратьОператорДля();
		КонецЕсли;
	ИначеЕсли Парсер_Токен = Токены.Возврат Тогда
		Оператор = РазобратьОператорВозврат();
	ИначеЕсли Парсер_Токен = Токены.Прервать Тогда
		Оператор = РазобратьОператорПрервать();
	ИначеЕсли Парсер_Токен = Токены.Продолжить Тогда
		Оператор = РазобратьОператорПродолжить();
	ИначеЕсли Парсер_Токен = Токены.ВызватьИсключение Тогда
		Оператор = РазобратьОператорВызватьИсключение();
	ИначеЕсли Парсер_Токен = Токены.Выполнить Тогда
		Оператор = РазобратьОператорВыполнить();
	ИначеЕсли Парсер_Токен = Токены.Перейти Тогда
		Оператор = РазобратьОператорПерейти();
	ИначеЕсли Парсер_Токен = Токены.Метка Тогда
		Оператор = РазобратьОператорМетка();
	ИначеЕсли Парсер_Токен = Токены.ДобавитьОбработчик Тогда
		Оператор = РазобратьОператорДобавитьОбработчик();
	ИначеЕсли Парсер_Токен = Токены.УдалитьОбработчик Тогда
		Оператор = РазобратьОператорУдалитьОбработчик();
	ИначеЕсли Парсер_Токен = Токены._Область Тогда
		Оператор = РазобратьИнструкциюПрепроцессораОбласть();
	ИначеЕсли Парсер_Токен = Токены._КонецОбласти Тогда
		Оператор = РазобратьИнструкциюПрепроцессораКонецОбласти();
	ИначеЕсли Парсер_Токен = Токены._Если Тогда
		Оператор = РазобратьИнструкциюПрепроцессораЕсли();
	ИначеЕсли Парсер_Токен = Токены._ИначеЕсли Тогда
		Оператор = РазобратьИнструкциюПрепроцессораИначеЕсли();
	ИначеЕсли Парсер_Токен = Токены._Иначе Тогда
		Оператор = РазобратьИнструкциюПрепроцессораИначе();
	ИначеЕсли Парсер_Токен = Токены._КонецЕсли Тогда
		Оператор = РазобратьИнструкциюПрепроцессораКонецЕсли();
	ИначеЕсли Парсер_Токен = Токены._Вставка Тогда
		Оператор = РазобратьИнструкциюПрепроцессораВставка();
	ИначеЕсли Парсер_Токен = Токены._КонецВставки Тогда
		Оператор = РазобратьИнструкциюПрепроцессораКонецВставки();
	ИначеЕсли Парсер_Токен = Токены._Удаление Тогда
		Оператор = РазобратьИнструкциюПрепроцессораУдаление();
	ИначеЕсли Парсер_Токен = Токены._КонецУдаления Тогда
		Оператор = РазобратьИнструкциюПрепроцессораКонецУдаления();
	ИначеЕсли Парсер_Токен = Токены.ТочкаСЗапятой Тогда
		// NOP
	ИначеЕсли Парсер_Токен = Токены.Ждать Тогда
		Оператор = РазобратьВыражениеОператорЖдать();
	КонецЕсли;
	Возврат Оператор;
КонецФункции // РазобратьОператор()

Функция РазобратьОператорВызватьИсключение()
	Перем Выражение, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Если ТокеныНачалаВыражения.Найти(СледующийТокен()) <> Неопределено Тогда
		Выражение = РазобратьВыражение();
	КонецЕсли;
	Узел = Парсер_Узлы.ОператорВызватьИсключение.Добавить();
	Узел.Тип = Типы.ОператорВызватьИсключение;
	Узел.Выражение = Выражение;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьОператорВызватьИсключение()

Функция РазобратьОператорВыполнить()
	Перем Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Узел = Парсер_Узлы.ОператорВыполнить.Добавить();
	Узел.Тип = Типы.ОператорВыполнить;
	Узел.Выражение = РазобратьВыражение();
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьОператорВыполнить()

Функция РазобратьОператорПрисваиванияИлиВызоваПроцедуры()
	Перем ЛевыйОперанд, ЭтоВызов, ПравыйОперанд, Оператор, НоваяПеременная, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	ЛевыйОперанд = РазобратьВыражениеИдентификатор(Истина, НоваяПеременная, ЭтоВызов);
	Если ЭтоВызов Тогда
		Оператор = Парсер_Узлы.ОператорВызоваПроцедуры.Добавить();
		Оператор.Тип = Типы.ОператорВызоваПроцедуры;
		Оператор.Идентификатор = ЛевыйОперанд;
		Оператор.Начало = Начало;
		Оператор.Конец = Парсер_ДанныеПредыдущегоТокена;
	Иначе
		Ожидать(Токены.ЗнакРавно);
		СледующийТокен();
		ПравыйОперанд = РазобратьВыражение();
		Если НоваяПеременная <> Неопределено Тогда
			Парсер_Переменные.Вставить(НоваяПеременная.Имя, НоваяПеременная);
			Парсер_Окружение.АвтоПеременные.Добавить(НоваяПеременная.Объявление);
		КонецЕсли;
		Оператор = Парсер_Узлы.ОператорПрисваивания.Добавить();
		Оператор.Тип = Типы.ОператорПрисваивания;
		Оператор.ЛевыйОперанд = ЛевыйОперанд;
		Оператор.ПравыйОперанд = ПравыйОперанд;
		Оператор.Начало = Начало;
		Оператор.Конец = Парсер_ДанныеПредыдущегоТокена;
	КонецЕсли;
	Возврат Оператор;
КонецФункции // РазобратьОператорПрисваиванияИлиВызоваПроцедуры()

Функция РазобратьОператорЕсли()
	Перем Выражение, ТогдаОператоры, ОператорИначе, СписокИначеЕсли, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Выражение = РазобратьВыражение();
	Ожидать(Токены.Тогда);
	СледующийТокен();
	ТогдаОператоры = РазобратьОператоры();
	Если Парсер_Токен = Токены.ИначеЕсли Тогда
		СписокИначеЕсли = Новый Массив;
		Пока Парсер_Токен = Токены.ИначеЕсли Цикл
			СписокИначеЕсли.Добавить(РазобратьОператорИначеЕсли());
		КонецЦикла;
	КонецЕсли;
	Если Парсер_Токен = Токены.Иначе Тогда
		ОператорИначе = РазобратьОператорИначе();
	КонецЕсли;
	Ожидать(Токены.КонецЕсли);
	СледующийТокен();
	Узел = Парсер_Узлы.ОператорЕсли.Добавить();
	Узел.Тип = Типы.ОператорЕсли;
	Узел.Выражение = Выражение;
	Узел.Тогда = ТогдаОператоры;
	Узел.ИначеЕсли = СписокИначеЕсли;
	Узел.Иначе = ОператорИначе;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьОператорЕсли()

Функция РазобратьОператорИначеЕсли()
	Перем ЕслиВыражение, ТогдаОператоры, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	ЕслиВыражение = РазобратьВыражение();
	Ожидать(Токены.Тогда);
	СледующийТокен();
	ТогдаОператоры = РазобратьОператоры();
	Узел = Парсер_Узлы.ОператорИначеЕсли.Добавить();
	Узел.Тип = Типы.ОператорИначеЕсли;
	Узел.Выражение = ЕслиВыражение;
	Узел.Тогда = ТогдаОператоры;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьОператорИначеЕсли()

Функция РазобратьОператорИначе()
	Перем Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Узел = Парсер_Узлы.ОператорИначе.Добавить();
	Узел.Тип = Типы.ОператорИначе;
	Узел.Операторы = РазобратьОператоры();
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьОператорИначе()

Функция РазобратьОператорПопытка()
	Перем Операторы, ОператорИсключение, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Операторы = РазобратьОператоры();
	Ожидать(Токены.Исключение);
	ОператорИсключение = РазобратьОператорИсключение();
	Ожидать(Токены.КонецПопытки);
	СледующийТокен();
	Узел = Парсер_Узлы.ОператорПопытка.Добавить();
	Узел.Тип = Типы.ОператорПопытка;
	Узел.Попытка = Операторы;
	Узел.Исключение = ОператорИсключение;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьОператорПопытка()

Функция РазобратьОператорИсключение()
	Перем Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Узел = Парсер_Узлы.ОператорИсключение.Добавить();
	Узел.Тип = Типы.ОператорИсключение;
	Узел.Операторы = РазобратьОператоры();
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьОператорИсключение()

Функция РазобратьОператорПока()
	Перем Выражение, Операторы, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Выражение = РазобратьВыражение();
	Ожидать(Токены.Цикл);
	СледующийТокен();
	Операторы = РазобратьОператоры();
	Ожидать(Токены.КонецЦикла);
	СледующийТокен();
	Узел = Парсер_Узлы.ОператорПока.Добавить();
	Узел.Тип = Типы.ОператорПока;
	Узел.Выражение = Выражение;
	Узел.Операторы = Операторы;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьОператорПока()

Функция РазобратьОператорДля()
	Перем ВыражениеИдентификатор, ЭтоВызов, Начало, Операторы, ИндексТокенаПеременной, НоваяПеременная, Старт, Финиш;
	Начало = Парсер_ДанныеПредыдущегоТокена;
	Ожидать(Токены.Идентификатор);
	ИндексТокенаПеременной = Парсер_ДанныеТекущегоТокена;
	ВыражениеИдентификатор = РазобратьВыражениеИдентификатор(Истина, НоваяПеременная, ЭтоВызов);
	Если ЭтоВызов Тогда
		Ошибка(14, Неопределено, Истина, ИндексТокенаПеременной);
	КонецЕсли;
	Ожидать(Токены.ЗнакРавно);
	СледующийТокен();
	Старт = РазобратьВыражение();
	Ожидать(Токены.По);
	СледующийТокен();
	Финиш = РазобратьВыражение();
	Если НоваяПеременная <> Неопределено Тогда
		Парсер_Переменные.Вставить(НоваяПеременная.Имя, НоваяПеременная);
		Парсер_Окружение.АвтоПеременные.Добавить(НоваяПеременная.Объявление);
	КонецЕсли;
	Ожидать(Токены.Цикл);
	СледующийТокен();
	Операторы = РазобратьОператоры();
	Ожидать(Токены.КонецЦикла);
	СледующийТокен();
	Узел = Парсер_Узлы.ОператорДля.Добавить();
	Узел.Тип = Типы.ОператорДля;
	Узел.Идентификатор = ВыражениеИдентификатор;
	Узел.Старт = Старт;
	Узел.Финиш = Финиш;
	Узел.Операторы = Операторы;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьОператорДля()

Функция РазобратьОператорДляКаждого()
	Перем ВыражениеИдентификатор, ЭтоВызов, Коллекция, Операторы, ИндексТокенаПеременной, НоваяПеременная, Начало;
	Начало = Парсер_ДанныеПредыдущегоТокена;
	СледующийТокен();
	Ожидать(Токены.Идентификатор);
	ИндексТокенаПеременной = Парсер_ДанныеТекущегоТокена;
	ВыражениеИдентификатор = РазобратьВыражениеИдентификатор(Истина, НоваяПеременная, ЭтоВызов);
	Если ЭтоВызов Тогда
		Ошибка(14, Неопределено, Истина, ИндексТокенаПеременной);
	КонецЕсли;
	Ожидать(Токены.Из);
	СледующийТокен();
	Коллекция = РазобратьВыражение();
	Если НоваяПеременная <> Неопределено Тогда
		Парсер_Переменные.Вставить(НоваяПеременная.Имя, НоваяПеременная);
		Парсер_Окружение.АвтоПеременные.Добавить(НоваяПеременная.Объявление);
	КонецЕсли;
	Ожидать(Токены.Цикл);
	СледующийТокен();
	Операторы = РазобратьОператоры();
	Ожидать(Токены.КонецЦикла);
	СледующийТокен();
	Узел = Парсер_Узлы.ОператорДляКаждого.Добавить();
	Узел.Тип = Типы.ОператорДляКаждого;
	Узел.Идентификатор = ВыражениеИдентификатор;
	Узел.Коллекция = Коллекция;
	Узел.Операторы = Операторы;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьОператорДляКаждого()

Функция РазобратьОператорПерейти()
	Перем Метка, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Ожидать(Токены.Метка);
	Метка = Парсер_Литерал;
	СледующийТокен();
	Узел = Парсер_Узлы.ОператорПерейти.Добавить();
	Узел.Тип = Типы.ОператорПерейти;
	Узел.Метка = Метка;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьОператорПерейти()

Функция РазобратьОператорВозврат()
	Перем Выражение, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Если Парсер_ЭтоФункция Тогда
		Выражение = РазобратьВыражение();
	КонецЕсли;
	Узел = Парсер_Узлы.ОператорВозврат.Добавить();
	Узел.Тип = Типы.ОператорВозврат;
	Узел.Выражение = Выражение;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьОператорВозврат()

Функция РазобратьОператорПрервать()
	Перем Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Узел = Парсер_Узлы.ОператорПрервать.Добавить();
	Узел.Тип = Типы.ОператорПрервать;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьОператорПрервать()

Функция РазобратьОператорПродолжить()
	Перем Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Узел = Парсер_Узлы.ОператорПродолжить.Добавить();
	Узел.Тип = Типы.ОператорПродолжить;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьОператорПродолжить()

Функция РазобратьОператорМетка()
	Перем Метка, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Метка = Парсер_Литерал;
	СледующийТокен();
	Ожидать(Токены.Двоеточие);
	Парсер_Токен = Токены.ТочкаСЗапятой; // уловка
	Узел = Парсер_Узлы.ОператорМетка.Добавить();
	Узел.Тип = Типы.ОператорМетка;
	Узел.Метка = Метка;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеТекущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьОператорМетка()

Функция РазобратьОператорДобавитьОбработчик()
	Перем Событие, ОбработчикСобытия, ЭтоВызов, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Ожидать(Токены.Идентификатор);
	Событие = РазобратьВыражениеИдентификатор(Ложь, Неопределено, ЭтоВызов);
	Если ЭтоВызов Тогда
		Ошибка(15, Неопределено, Истина, Начало);
	КонецЕсли;
	Ожидать(Токены.Запятая);
	СледующийТокен();
	Ожидать(Токены.Идентификатор);
	ОбработчикСобытия = РазобратьВыражениеИдентификатор(Ложь, Неопределено, ЭтоВызов);
	Если ЭтоВызов Тогда
		Ошибка(16, Неопределено, Истина, Начало);
	КонецЕсли;
	Узел = Парсер_Узлы.ОператорДобавитьОбработчик.Добавить();
	Узел.Тип = Типы.ОператорДобавитьОбработчик;
	Узел.Событие = Событие;
	Узел.ОбработчикСобытия = ОбработчикСобытия;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьОператорДобавитьОбработчик()

Функция РазобратьОператорУдалитьОбработчик()
	Перем Событие, ОбработчикСобытия, ЭтоВызов, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Ожидать(Токены.Идентификатор);
	Событие = РазобратьВыражениеИдентификатор(Ложь, Неопределено, ЭтоВызов);
	Если ЭтоВызов Тогда
		Ошибка(15, Неопределено, Истина, Начало);
	КонецЕсли;
	Ожидать(Токены.Запятая);
	СледующийТокен();
	Ожидать(Токены.Идентификатор);
	ОбработчикСобытия = РазобратьВыражениеИдентификатор(Ложь, Неопределено, ЭтоВызов);
	Если ЭтоВызов Тогда
		Ошибка(16, Неопределено, Истина, Начало);
	КонецЕсли;
	Узел = Парсер_Узлы.ОператорУдалитьОбработчик.Добавить();
	Узел.Тип = Типы.ОператорУдалитьОбработчик;
	Узел.Событие = Событие;
	Узел.ОбработчикСобытия = ОбработчикСобытия;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьОператорУдалитьОбработчик()

#КонецОбласти // РазборОператоров

#Область РазборПрепроцессора

// Выражения

Функция РазобратьВыражениеПрепроцессора()
	Перем Выражение, Операция, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Выражение = РазобратьВыражениеПрепроцессораИ();
	Пока Парсер_Токен = Токены.Или Цикл
		Операция = Парсер_ДанныеТекущегоТокена;
		СледующийТокен();
		ЛевыйОперанд = Выражение;
		Выражение = Парсер_Узлы.ВыражениеПрепроцессораБинарное.Добавить();
		Выражение.Тип = Типы.ВыражениеПрепроцессораБинарное;
		Выражение.ЛевыйОперанд = ЛевыйОперанд;
		Выражение.Операция = Операция;
		Выражение.ПравыйОперанд = РазобратьВыражениеПрепроцессораИ();
		Выражение.Начало = Начало;
		Выражение.Конец = Парсер_ДанныеПредыдущегоТокена;
	КонецЦикла;
	Возврат Выражение;
КонецФункции // РазобратьВыражениеПрепроцессора()

Функция РазобратьВыражениеПрепроцессораИ()
	Перем Выражение, Операция, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Выражение = РазобратьВыражениеПрепроцессораНе();
	Пока Парсер_Токен = Токены.И Цикл
		Операция = Парсер_ДанныеТекущегоТокена;
		СледующийТокен();
		ЛевыйОперанд = Выражение;
		Выражение = Парсер_Узлы.ВыражениеПрепроцессораБинарное.Добавить();
		Выражение.Тип = Типы.ВыражениеПрепроцессораБинарное;
		Выражение.ЛевыйОперанд = ЛевыйОперанд;
		Выражение.Операция = Операция;
		Выражение.ПравыйОперанд = РазобратьВыражениеПрепроцессораНе();
		Выражение.Начало = Начало;
		Выражение.Конец = Парсер_ДанныеПредыдущегоТокена;
	КонецЦикла;
	Возврат Выражение;
КонецФункции // РазобратьВыражениеПрепроцессораИ()

Функция РазобратьВыражениеПрепроцессораНе()
	Перем Выражение, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Если Парсер_Токен = Токены.Не Тогда
		СледующийТокен();
		Выражение = Парсер_Узлы.ВыражениеПрепроцессораНе.Добавить();
		Выражение.Тип = Типы.ВыражениеПрепроцессораНе;
		Выражение.Выражение = РазобратьВыражениеПрепроцессораОперанд();
		Выражение.Начало = Начало;
		Выражение.Конец = Парсер_ДанныеПредыдущегоТокена;
	Иначе
		Выражение = РазобратьВыражениеПрепроцессораОперанд();
	КонецЕсли;
	Возврат Выражение;
КонецФункции // РазобратьВыражениеПрепроцессораНе()

Функция РазобратьВыражениеПрепроцессораОперанд()
	Перем Операнд;
	Если Парсер_Токен = Токены.Идентификатор Тогда
		Операнд = РазобратьВыражениеПрепроцессораСимвол();
	ИначеЕсли Парсер_Токен = Токены.ЛеваяКруглаяСкобка Тогда
		Операнд = РазобратьВыражениеПрепроцессораСкобочное();
	Иначе
		Ошибка(7, Неопределено, Истина, Парсер_ДанныеТекущегоТокена);
	КонецЕсли;
	Возврат Операнд;
КонецФункции

Функция РазобратьВыражениеПрепроцессораСимвол()
	Перем Символ, СимволСуществует;
	СимволСуществует = СимволыПрепроцессора.Свойство(Парсер_Литерал);
	Символ = Парсер_Узлы.ВыражениеПрепроцессораСимвол.Добавить();
	Символ.Тип = Типы.ВыражениеПрепроцессораСимвол;
	Символ.Символ = Парсер_Литерал;
	Символ.Существует = СимволСуществует;
	Символ.Начало = Парсер_ДанныеТекущегоТокена;
	Символ.Конец = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Возврат Символ;
КонецФункции // РазобратьВыражениеПрепроцессораСимвол()

Функция РазобратьВыражениеПрепроцессораСкобочное()
	Перем Выражение, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Выражение = РазобратьВыражениеПрепроцессора();
	Ожидать(Токены.ПраваяКруглаяСкобка);
	СледующийТокен();
	Узел = Парсер_Узлы.ВыражениеПрепроцессораСкобочное.Добавить();
	Узел.Тип = Типы.ВыражениеПрепроцессораСкобочное;
	Узел.Выражение = Выражение;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьВыражениеПрепроцессораСкобочное()

// Инструкции

Функция РазобратьИнструкциюПрепроцессораЕсли()
	Перем Выражение, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Выражение = РазобратьВыражениеПрепроцессора();
	Ожидать(Токены.Тогда);
	Парсер_Токен = Токены.ТочкаСЗапятой; // уловка
	Узел = Парсер_Узлы.ИнструкцияПрепроцессораЕсли.Добавить();
	Узел.Тип = Типы.ИнструкцияПрепроцессораЕсли;
	Узел.Выражение = Выражение;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеТекущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьИнструкциюПрепроцессораЕсли()

Функция РазобратьИнструкциюПрепроцессораИначеЕсли()
	Перем Выражение, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Выражение = РазобратьВыражениеПрепроцессора();
	Ожидать(Токены.Тогда);
	Парсер_Токен = Токены.ТочкаСЗапятой; // уловка
	Узел = Парсер_Узлы.ИнструкцияПрепроцессораИначеЕсли.Добавить();
	Узел.Тип = Типы.ИнструкцияПрепроцессораИначеЕсли;
	Узел.Выражение = Выражение;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеПредыдущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьИнструкциюПрепроцессораИначеЕсли()

Функция РазобратьИнструкциюПрепроцессораИначе()
	Перем Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Парсер_Токен = Токены.ТочкаСЗапятой; // уловка
	Узел = Парсер_Узлы.ИнструкцияПрепроцессораИначе.Добавить();
	Узел.Тип = Типы.ИнструкцияПрепроцессораИначе;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеТекущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьИнструкциюПрепроцессораИначе()

Функция РазобратьИнструкциюПрепроцессораКонецЕсли()
	Перем Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Парсер_Токен = Токены.ТочкаСЗапятой; // уловка
	Узел = Парсер_Узлы.ИнструкцияПрепроцессораКонецЕсли.Добавить();
	Узел.Тип = Типы.ИнструкцияПрепроцессораКонецЕсли;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеТекущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьИнструкциюПрепроцессораКонецЕсли()

Функция РазобратьИнструкциюПрепроцессораОбласть()
	Перем Имя, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Ожидать(Токены.Идентификатор);
	Имя = Парсер_Литерал;
	Парсер_Токен = Токены.ТочкаСЗапятой; // уловка
	Узел = Парсер_Узлы.ИнструкцияПрепроцессораОбласть.Добавить();
	Узел.Тип = Типы.ИнструкцияПрепроцессораОбласть;
	Узел.Имя = Имя;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеТекущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьИнструкциюПрепроцессораОбласть()

Функция РазобратьИнструкциюПрепроцессораКонецОбласти()
	Перем Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Парсер_Токен = Токены.ТочкаСЗапятой; // уловка
	Узел = Парсер_Узлы.ИнструкцияПрепроцессораКонецОбласти.Добавить();
	Узел.Тип = Типы.ИнструкцияПрепроцессораКонецОбласти;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеТекущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьИнструкциюПрепроцессораКонецОбласти()

Функция РазобратьИнструкциюПрепроцессораВставка()
	Перем Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Парсер_Токен = Токены.ТочкаСЗапятой; // уловка
	Узел = Парсер_Узлы.ИнструкцияПрепроцессораВставка.Добавить();
	Узел.Тип = Типы.ИнструкцияПрепроцессораВставка;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеТекущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьИнструкциюПрепроцессораВставка()

Функция РазобратьИнструкциюПрепроцессораКонецВставки()
	Перем Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Парсер_Токен = Токены.ТочкаСЗапятой; // уловка
	Узел = Парсер_Узлы.ИнструкцияПрепроцессораКонецВставки.Добавить();
	Узел.Тип = Типы.ИнструкцияПрепроцессораКонецВставки;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеТекущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьИнструкциюПрепроцессораКонецВставки()

Функция РазобратьИнструкциюПрепроцессораУдаление()
	Перем Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Парсер_Токен = Токены.ТочкаСЗапятой; // уловка
	Узел = Парсер_Узлы.ИнструкцияПрепроцессораУдаление.Добавить();
	Узел.Тип = Типы.ИнструкцияПрепроцессораУдаление;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеТекущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьИнструкциюПрепроцессораУдаление()

Функция РазобратьИнструкциюПрепроцессораКонецУдаления()
	Перем Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	Парсер_Токен = Токены.ТочкаСЗапятой; // уловка
	Узел = Парсер_Узлы.ИнструкцияПрепроцессораКонецУдаления.Добавить();
	Узел.Тип = Типы.ИнструкцияПрепроцессораКонецУдаления;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеТекущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьИнструкциюПрепроцессораКонецУдаления()

Функция РазобратьИнструкциюПрепроцессораИспользовать()
	Перем Путь, Начало;
	Начало = Парсер_ДанныеТекущегоТокена;
	СледующийТокен();
	Если Парсер_НомерТекущейСтроки <> Начало.НомерСтроки Тогда
		Ошибка(20, Неопределено, Истина, Парсер_ДанныеТекущегоТокена);
	КонецЕсли;
	Если Парсер_Токен = Токены.Число Тогда
		Путь = Парсер_Литерал;
		Если КартаБуквЦифр[Парсер_Символ] = Буква Тогда
			СледующийТокен();
			Путь = Путь + Парсер_Литерал;
		КонецЕсли;
	ИначеЕсли Парсер_Токен = Токены.Идентификатор
		Или Парсер_Токен = Токены.Строка Тогда
		Путь = Парсер_Литерал;
	Иначе
		Ошибка(20, Неопределено, Истина, Парсер_ДанныеТекущегоТокена);
	КонецЕсли;	
	Парсер_Токен = Токены.ТочкаСЗапятой; // уловка
	Узел = Парсер_Узлы.ИнструкцияПрепроцессораИспользовать.Добавить();
	Узел.Тип = Типы.ИнструкцияПрепроцессораИспользовать;
	Узел.Путь = Путь;
	Узел.Начало = Начало;
	Узел.Конец = Парсер_ДанныеТекущегоТокена;
	Возврат Узел;
КонецФункции // РазобратьИнструкциюПрепроцессораИспользовать()

#КонецОбласти // РазборПрепроцессора

#КонецОбласти // Парсер

#Область СлужебныеМетоды

Функция Доступность(Клиент, ВнешнееСоединение, МобильноеПриложение, МобильныйКлиент, МобильныйСервер, Сервер, ТолстыйКлиент, ТонкийКлиент, ВебКлиент, Интеграция) Экспорт
	Возврат Новый Структура(
	"Клиент, ВнешнееСоединение, МобильноеПриложение, МобильныйКлиент, МобильныйСервер, Сервер, ТолстыйКлиент, ТонкийКлиент, ВебКлиент, Интеграция",
	Клиент, ВнешнееСоединение, МобильноеПриложение, МобильныйКлиент, МобильныйСервер, Сервер, ТолстыйКлиент, ТонкийКлиент, ВебКлиент, Интеграция
);
КонецФункции

Функция КакДата(ЛитералДаты)
	Перем Список, Символ, Позиция, ДатаСтрокой, Дата;
	Список = Новый Массив;
	Для Позиция = 1 По СтрДлина(ЛитералДаты) Цикл
		Символ = Сред(ЛитералДаты, Позиция, 1);
		Если КартаБуквЦифр[Символ] = Цифра Тогда
			Список.Добавить(Символ);
		КонецЕсли;
	КонецЦикла;
	ДатаСтрокой = СтрСоединить(Список);
	Если ДатаСтрокой = "00000000"
		Или ДатаСтрокой = "000000000000"
		Или ДатаСтрокой = "00000000000000" Тогда
		Возврат '00010101';
	КонецЕсли;
	Попытка
		Дата = Дата(ДатаСтрокой);
	Исключение
		Ошибка(18, ЛитералДаты, Истина);
	КонецПопытки;
	Возврат Дата;
КонецФункции // КакДата()

Процедура Ожидать(Токен)
	Если Парсер_Токен <> Токен Тогда
		Ошибка(1, Токен, Истина, Парсер_ДанныеТекущегоТокена);
	КонецЕсли;
КонецПроцедуры // Ожидать()

Процедура Ошибка(Код, Аргумент, Остановить, Начало = Неопределено, Конец = Неопределено)
	Перем Ошибка, ТокенНачала, ТокенКонца;
	Ошибка = Парсер_Ошибки.Добавить();
	Ошибка.Источник = "ПарсерВстроенногоЯзыка";
	Ошибка.Код = Код;
	Ошибка.Текст = Ошибки[Код] + ?(Аргумент = Неопределено, "", ": " + Аргумент);
	Если Начало = Неопределено Тогда
		ТокенНачала = Новый Структура;
		ТокенНачала.Вставить("Токен", Неопределено);
		ТокенНачала.Вставить("НомерСтроки", Парсер_НомерТекущейСтроки);
		ТокенНачала.Вставить("НомерКолонки", Парсер_ПозицияНачалаТокена - Парсер_ПозицияТекущейСтроки);
		ТокенНачала.Вставить("Позиция", Парсер_ПозицияНачалаТокена);
		ТокенНачала.Вставить("Длина", Парсер_ТекущаяПозиция - Парсер_ПозицияНачалаТокена);
	Иначе
		ТокенНачала = Начало;
	КонецЕсли;
	Если Конец = Неопределено Тогда
		ТокенКонца = ТокенНачала;
	Иначе
		ТокенКонца = Конец;
	КонецЕсли;
	Ошибка.ПозицияНачала = Мин(ТокенНачала.Позиция, Парсер_ДлинаИсходника);
	Ошибка.НомерСтрокиНачала = ТокенНачала.НомерСтроки;
	Ошибка.НомерКолонкиНачала = ТокенНачала.НомерКолонки;
	Ошибка.ПозицияКонца = Мин(ТокенКонца.Позиция + ТокенКонца.Длина, Парсер_ДлинаИсходника + 1);
	Ошибка.НомерСтрокиКонца = ТокенКонца.НомерСтроки;
	Ошибка.НомерКолонкиКонца = ТокенКонца.НомерКолонки;
	Если Остановить Тогда
		ВызватьИсключение Ошибка.Текст;
	КонецЕсли;
КонецПроцедуры // Ошибка()

#КонецОбласти // СлужебныеМетоды

#Область Посетитель

Процедура Подключить(Знач Плагины) Экспорт
	Перем Плагин, Список, ИмяПроцедуры;
	Если ТипЗнч(Плагины) <> Тип("Массив") Тогда
		Плагин = Плагины;
		Плагины = Новый Массив;
		Плагины.Добавить(Плагин);
	КонецЕсли;
	Посетитель_Плагины = Плагины;
	Посетитель_Подписки = Подписки();
	Для Каждого Плагин Из Плагины Цикл
		Список = Неопределено;
		Для Каждого ИмяПроцедуры Из Плагин.Подписки() Цикл
			Если Посетитель_Подписки.Свойство(ИмяПроцедуры, Список) Тогда
				Список.Добавить(Плагин);
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;
КонецПроцедуры // Подключить()

Функция Стек() Экспорт
	Возврат Посетитель_Стек;
КонецФункции

Функция Счетчики() Экспорт
	Возврат Посетитель_Счетчики;
КонецФункции

Процедура ДобавитьНаСтек(Узел)
	Посетитель_Стек.Добавить(Узел);
	Посетитель_Счетчики[Узел.Тип] = Посетитель_Счетчики[Узел.Тип] + 1;
КонецПроцедуры // ДобавитьНаСтек()

Процедура УдалитьСоСтека()
	Перем Узел, Вершина;
	Вершина = Посетитель_Стек.ВГраница();
	Узел = Посетитель_Стек[Вершина];
	Посетитель_Счетчики[Узел.Тип] = Посетитель_Счетчики[Узел.Тип] - 1;
	Посетитель_Стек.Удалить(Вершина);
КонецПроцедуры // УдалитьСоСтека()

Функция Подписки()
	Перем Подписки, Элемент;
	
	Подписки = Новый Структура(
	"ПосетитьМодуль,                              ПокинутьМодуль,"
	"ПосетитьОбъявления,                          ПокинутьОбъявления,"
	"ПосетитьОператоры,                           ПокинутьОператоры,"
	"ПосетитьОбъявлениеСпискаПеременныхМодуля,    ПокинутьОбъявлениеСпискаПеременныхМодуля,"
	"ПосетитьОбъявлениеПеременнойМодуля,          ПокинутьОбъявлениеПеременнойМодуля,"
	"ПосетитьОбъявлениеСпискаЛокальныхПеременных, ПокинутьОбъявлениеСпискаЛокальныхПеременных,"
	"ПосетитьОбъявлениеЛокальнойПеременной,       ПокинутьОбъявлениеЛокальнойПеременной,"
	"ПосетитьОбъявлениеПараметра,                 ПокинутьОбъявлениеПараметра,"
	"ПосетитьОбъявлениеМетода,                    ПокинутьОбъявлениеМетода,"
	"ПосетитьСигнатуру,                           ПокинутьСигнатуру,"
	"ПосетитьВыражение,                           ПокинутьВыражение,"           // вызываются один раз для корня выражения
	"ПосетитьВыражениеЛитерал,                    ПокинутьВыражениеЛитерал,"
	"ПосетитьВыражениеИдентификатор,              ПокинутьВыражениеИдентификатор,"
	"ПосетитьВыражениеУнарное,                    ПокинутьВыражениеУнарное,"
	"ПосетитьВыражениеБинарное,                   ПокинутьВыражениеБинарное,"
	"ПосетитьВыражениеНовый,                      ПокинутьВыражениеНовый,"
	"ПосетитьВыражениеТернарное,                  ПокинутьВыражениеТернарное,"
	"ПосетитьВыражениеСкобочное,                  ПокинутьВыражениеСкобочное,"
	"ПосетитьВыражениеНе,                         ПокинутьВыражениеНе,"
	"ПосетитьВыражениеСтроковое,                  ПокинутьВыражениеСтроковое,"
	"ПосетитьОператорПрисваивания,                ПокинутьОператорПрисваивания,"
	"ПосетитьОператорВозврат,                     ПокинутьОператорВозврат,"
	"ПосетитьОператорПрервать,                    ПокинутьОператорПрервать,"
	"ПосетитьОператорПродолжить,                  ПокинутьОператорПродолжить,"
	"ПосетитьОператорВызватьИсключение,           ПокинутьОператорВызватьИсключение,"
	"ПосетитьОператорВыполнить,                   ПокинутьОператорВыполнить,"
	"ПосетитьОператорВызоваПроцедуры,             ПокинутьОператорВызоваПроцедуры,"
	"ПосетитьОператорЕсли,                        ПокинутьОператорЕсли,"
	"ПосетитьОператорИначеЕсли,                   ПокинутьОператорИначеЕсли,"
	"ПосетитьОператорИначе,                       ПокинутьОператорИначе,"
	"ПосетитьОператорПока,                        ПокинутьОператорПока,"
	"ПосетитьОператорДля,                         ПокинутьОператорДля,"
	"ПосетитьОператорДляКаждого,                  ПокинутьОператорДляКаждого,"
	"ПосетитьОператорПопытка,                     ПокинутьОператорПопытка,"
	"ПосетитьОператорИсключение,                  ПокинутьОператорИсключение,"
	"ПосетитьОператорПерейти,                     ПокинутьОператорПерейти,"
	"ПосетитьОператорМетка,                       ПокинутьОператорМетка,"
	"ПосетитьОператорДобавитьОбработчик,          ПокинутьОператорДобавитьОбработчик,"
	"ПосетитьОператорУдалитьОбработчик,           ПокинутьОператорУдалитьОбработчик,"
	"ПосетитьИнструкциюПрепроцессора,             ПокинутьИнструкциюПрепроцессора,"
	"ПосетитьВыражениеПрепроцессора,              ПокинутьВыражениеПрепроцессора,"
	"ПосетитьВыражениеПрепроцессораБинарное,      ПокинутьВыражениеПрепроцессораБинарное,"
	"ПосетитьВыражениеПрепроцессораНе,            ПокинутьВыражениеПрепроцессораНе,"
	"ПосетитьВыражениеПрепроцессораСимвол,        ПокинутьВыражениеПрепроцессораСимвол,"
	"ПосетитьВыражениеПрепроцессораСкобочное,     ПокинутьВыражениеПрепроцессораСкобочное"
);

Для Каждого Элемент Из Подписки Цикл
	Подписки[Элемент.Ключ] = Новый Массив;
КонецЦикла;

Возврат Подписки;
КонецФункции // Подписки()

Процедура Посетить(Модуль, Параметры = Неопределено) Экспорт
	Перем Плагин, Подписка, Элемент, ПараметрыПлагина;
	Если Параметры = Неопределено Тогда
		Параметры = Новый Соответствие;
	КонецЕсли;
	Посетитель_Стек = Новый Массив;
	Посетитель_Счетчики = Новый Структура;
	Для Каждого Элемент Из Типы Цикл
		Посетитель_Счетчики.Вставить(Элемент.Ключ, 0);
	КонецЦикла;
	Для Каждого Плагин Из Посетитель_Плагины Цикл
		Попытка
			// 1С - на платформе обработка не может быть ключом соответствия, но свойство ЭтотОбъект может
			// ¯\_(ツ)_/¯
			ПараметрыПлагина = Параметры[Плагин.ЭтотОбъект];
		Исключение
			// onescript
			ПараметрыПлагина = Параметры[Плагин];
		КонецПопытки;
		Плагин.Открыть(ЭтотОбъект, ПараметрыПлагина);
	КонецЦикла;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьМодуль Цикл
		Подписка.ПосетитьМодуль(Модуль);
	КонецЦикла;
	ДобавитьНаСтек(Модуль);
	ПосетитьОбъявления(Модуль.Объявления);
	ПосетитьОператоры(Модуль.Операторы);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьМодуль Цикл
		Подписка.ПокинутьМодуль(Модуль);
	КонецЦикла;
КонецПроцедуры // Посетить()

Процедура ПосетитьОбъявления(Объявления)
	Перем Объявление, Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОбъявления Цикл
		Подписка.ПосетитьОбъявления(Объявления);
	КонецЦикла;
	Для Каждого Объявление Из Объявления Цикл
		ПосетитьОбъявлениеПоТипу(Объявление);
	КонецЦикла;
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОбъявления Цикл
		Подписка.ПокинутьОбъявления(Объявления);
	КонецЦикла;
КонецПроцедуры // ПосетитьОбъявления()

Процедура ПосетитьОператоры(Операторы)
	Перем Оператор, Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператоры Цикл
		Подписка.ПосетитьОператоры(Операторы);
	КонецЦикла;
	Для Каждого Оператор Из Операторы Цикл
		ПосетитьОператорПоТипу(Оператор);
	КонецЦикла;
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператоры Цикл
		Подписка.ПокинутьОператоры(Операторы);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператоры()

#Область ПосещениеОбъявлений

Процедура ПосетитьОбъявлениеПоТипу(Объявление)
	Перем Тип;
	Тип = Объявление.Тип;
	Если Тип = Типы.ОбъявлениеСпискаПеременныхМодуля Тогда
		ПосетитьОбъявлениеСпискаПеременныхМодуля(Объявление);
	ИначеЕсли Тип = Типы.ОбъявлениеЛокальнойПеременной Тогда
		ПосетитьОбъявлениеЛокальнойПеременной(Объявление);
	ИначеЕсли Тип = Типы.ОбъявлениеМетода Тогда
		ПосетитьОбъявлениеМетода(Объявление);
	ИначеЕсли Тип = Типы.ИнструкцияПрепроцессораОбласть
		Или Тип = Типы.ИнструкцияПрепроцессораКонецОбласти
		Или Тип = Типы.ИнструкцияПрепроцессораЕсли
		Или Тип = Типы.ИнструкцияПрепроцессораИначеЕсли
		Или Тип = Типы.ИнструкцияПрепроцессораИначе
		Или Тип = Типы.ИнструкцияПрепроцессораКонецЕсли
		Или Тип = Типы.ИнструкцияПрепроцессораИспользовать Тогда
		ПосетитьИнструкциюПрепроцессора(Объявление);
	КонецЕсли;
КонецПроцедуры // ПосетитьОбъявлениеПоТипу()

Процедура ПосетитьОбъявлениеСпискаПеременныхМодуля(ОбъявлениеСпискаПеременныхМодуля)
	Перем Подписка, ОбъявлениеПеременнойМодуля;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОбъявлениеСпискаПеременныхМодуля Цикл
		Подписка.ПосетитьОбъявлениеСпискаПеременныхМодуля(ОбъявлениеСпискаПеременныхМодуля);
	КонецЦикла;
	ДобавитьНаСтек(ОбъявлениеСпискаПеременныхМодуля);
	Для Каждого ОбъявлениеПеременнойМодуля Из ОбъявлениеСпискаПеременныхМодуля.Объявления Цикл
		ПосетитьОбъявлениеПеременнойМодуля(ОбъявлениеПеременнойМодуля);
	КонецЦикла;
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОбъявлениеСпискаПеременныхМодуля Цикл
		Подписка.ПокинутьОбъявлениеСпискаПеременныхМодуля(ОбъявлениеСпискаПеременныхМодуля);
	КонецЦикла;
КонецПроцедуры // ПосетитьОбъявлениеСпискаПеременныхМодуля()

Процедура ПосетитьОбъявлениеПеременнойМодуля(ОбъявлениеПеременнойМодуля)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОбъявлениеПеременнойМодуля Цикл
		Подписка.ПосетитьОбъявлениеПеременнойМодуля(ОбъявлениеПеременнойМодуля);
	КонецЦикла;
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОбъявлениеПеременнойМодуля Цикл
		Подписка.ПокинутьОбъявлениеПеременнойМодуля(ОбъявлениеПеременнойМодуля);
	КонецЦикла;
КонецПроцедуры // ПосетитьОбъявлениеПеременнойМодуля()

Процедура ПосетитьОбъявлениеСпискаЛокальныхПеременных(ОбъявлениеСпискаЛокальныхПеременных)
	Перем Подписка, ОбъявлениеЛокальнойПеременной;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОбъявлениеСпискаЛокальныхПеременных Цикл
		Подписка.ПосетитьОбъявлениеСпискаЛокальныхПеременных(ОбъявлениеСпискаЛокальныхПеременных);
	КонецЦикла;
	ДобавитьНаСтек(ОбъявлениеСпискаЛокальныхПеременных);
	Для Каждого ОбъявлениеЛокальнойПеременной Из ОбъявлениеСпискаЛокальныхПеременных.Объявления Цикл
		ПосетитьОбъявлениеЛокальнойПеременной(ОбъявлениеЛокальнойПеременной);
	КонецЦикла;
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОбъявлениеСпискаЛокальныхПеременных Цикл
		Подписка.ПокинутьОбъявлениеСпискаЛокальныхПеременных(ОбъявлениеСпискаЛокальныхПеременных);
	КонецЦикла;
КонецПроцедуры // ПосетитьОбъявлениеСпискаЛокальныхПеременных()

Процедура ПосетитьОбъявлениеЛокальнойПеременной(ОбъявлениеЛокальнойПеременной)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОбъявлениеЛокальнойПеременной Цикл
		Подписка.ПосетитьОбъявлениеЛокальнойПеременной(ОбъявлениеЛокальнойПеременной);
	КонецЦикла;
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОбъявлениеЛокальнойПеременной Цикл
		Подписка.ПокинутьОбъявлениеЛокальнойПеременной(ОбъявлениеЛокальнойПеременной);
	КонецЦикла;
КонецПроцедуры // ПосетитьОбъявлениеЛокальнойПеременной()

Процедура ПосетитьОбъявлениеПараметра(ОбъявлениеПараметра)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОбъявлениеПараметра Цикл
		Подписка.ПосетитьОбъявлениеПараметра(ОбъявлениеПараметра);
	КонецЦикла;
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОбъявлениеПараметра Цикл
		Подписка.ПокинутьОбъявлениеПараметра(ОбъявлениеПараметра);
	КонецЦикла;
КонецПроцедуры // ПосетитьОбъявлениеПараметра()

Процедура ПосетитьОбъявлениеМетода(ОбъявлениеМетода)
	Перем Подписка, ОбъявлениеСпискаЛокальныхПеременных;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОбъявлениеМетода Цикл
		Подписка.ПосетитьОбъявлениеМетода(ОбъявлениеМетода);
	КонецЦикла;
	ДобавитьНаСтек(ОбъявлениеМетода);
	ПосетитьСигнатуру(ОбъявлениеМетода.Сигнатура);
	Для Каждого ОбъявлениеСпискаЛокальныхПеременных Из ОбъявлениеМетода.Объявления Цикл
		ПосетитьОбъявлениеСпискаЛокальныхПеременных(ОбъявлениеСпискаЛокальныхПеременных);
	КонецЦикла;
	ПосетитьОператоры(ОбъявлениеМетода.Операторы);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОбъявлениеМетода Цикл
		Подписка.ПокинутьОбъявлениеМетода(ОбъявлениеМетода);
	КонецЦикла;
КонецПроцедуры // ПосетитьОбъявлениеМетода()

Процедура ПосетитьСигнатуру(Сигнатура)
	Перем Подписка, ОбъявлениеПараметра;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьСигнатуру Цикл
		Подписка.ПосетитьСигнатуру(Сигнатура);
	КонецЦикла;
	ДобавитьНаСтек(Сигнатура);
	Для Каждого ОбъявлениеПараметра Из Сигнатура.Параметры Цикл
		ПосетитьОбъявлениеПараметра(ОбъявлениеПараметра);
	КонецЦикла;
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьСигнатуру Цикл
		Подписка.ПокинутьСигнатуру(Сигнатура);
	КонецЦикла;
КонецПроцедуры // ПосетитьСигнатуру()

#КонецОбласти // ПосещениеОбъявлений

#Область ПосещениеВыражений

Процедура ПосетитьВыражение(Выражение)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьВыражение Цикл
		Подписка.ПосетитьВыражение(Выражение);
	КонецЦикла;
	ПосетитьВыражениеПоТипу(Выражение);
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьВыражение Цикл
		Подписка.ПокинутьВыражение(Выражение);
	КонецЦикла;
КонецПроцедуры // ПосетитьВыражение()

Процедура ПосетитьВыражениеПоТипу(Выражение)
	Перем Тип;
	Тип = Выражение.Тип;
	Если Тип = Типы.ВыражениеЛитерал Тогда
		ПосетитьВыражениеЛитерал(Выражение);
	ИначеЕсли Тип = Типы.ВыражениеИдентификатор Тогда
		ПосетитьВыражениеИдентификатор(Выражение);
	ИначеЕсли Тип = Типы.ВыражениеУнарное Тогда
		ПосетитьВыражениеУнарное(Выражение);
	ИначеЕсли Тип = Типы.ВыражениеБинарное Тогда
		ПосетитьВыражениеБинарное(Выражение);
	ИначеЕсли Тип = Типы.ВыражениеНовый Тогда
		ПосетитьВыражениеНовый(Выражение);
	ИначеЕсли Тип = Типы.ВыражениеТернарное Тогда
		ПосетитьВыражениеТернарное(Выражение);
	ИначеЕсли Тип = Типы.ВыражениеСкобочное Тогда
		ПосетитьВыражениеСкобочное(Выражение);
	ИначеЕсли Тип = Типы.ВыражениеНе Тогда
		ПосетитьВыражениеНе(Выражение);
	ИначеЕсли Тип = Типы.ВыражениеСтроковое Тогда
		ПосетитьВыражениеСтроковое(Выражение);
	КонецЕсли;
КонецПроцедуры // ПосетитьВыражениеПоТипу()

Процедура ПосетитьВыражениеЛитерал(ВыражениеЛитерал)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьВыражениеЛитерал Цикл
		Подписка.ПосетитьВыражениеЛитерал(ВыражениеЛитерал);
	КонецЦикла;
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьВыражениеЛитерал Цикл
		Подписка.ПокинутьВыражениеЛитерал(ВыражениеЛитерал);
	КонецЦикла;
КонецПроцедуры // ПосетитьВыражениеЛитерал()

Процедура ПосетитьВыражениеИдентификатор(ВыражениеИдентификатор)
	Перем Элемент, Выражение, Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьВыражениеИдентификатор Цикл
		Подписка.ПосетитьВыражениеИдентификатор(ВыражениеИдентификатор);
	КонецЦикла;
	ДобавитьНаСтек(ВыражениеИдентификатор);
	Если ВыражениеИдентификатор.Аргументы <> Неопределено Тогда
		Для Каждого Выражение Из ВыражениеИдентификатор.Аргументы Цикл
			Если Выражение <> Неопределено Тогда
				ПосетитьВыражениеПоТипу(Выражение);
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	Для Каждого Элемент Из ВыражениеИдентификатор.Хвост Цикл
		Если Элемент.Тип = Типы.ВыражениеПоле Тогда
			Если Элемент.Аргументы <> Неопределено Тогда
				Для Каждого Выражение Из Элемент.Аргументы Цикл
					Если Выражение <> Неопределено Тогда
						ПосетитьВыражениеПоТипу(Выражение);
					КонецЕсли;
				КонецЦикла;
			КонецЕсли;
		ИначеЕсли Элемент.Тип = Типы.ВыражениеИндекс Тогда
			ПосетитьВыражениеПоТипу(Элемент.Выражение);
		Иначе
			ВызватьИсключение "нарушение протокола";
		КонецЕсли;
	КонецЦикла;
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьВыражениеИдентификатор Цикл
		Подписка.ПокинутьВыражениеИдентификатор(ВыражениеИдентификатор);
	КонецЦикла;
КонецПроцедуры // ПосетитьВыражениеИдентификатор()

Процедура ПосетитьВыражениеУнарное(ВыражениеУнарное)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьВыражениеУнарное Цикл
		Подписка.ПосетитьВыражениеУнарное(ВыражениеУнарное);
	КонецЦикла;
	ДобавитьНаСтек(ВыражениеУнарное);
	ПосетитьВыражениеПоТипу(ВыражениеУнарное.Операнд);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьВыражениеУнарное Цикл
		Подписка.ПокинутьВыражениеУнарное(ВыражениеУнарное);
	КонецЦикла;
КонецПроцедуры // ПосетитьВыражениеУнарное()

Процедура ПосетитьВыражениеБинарное(ВыражениеБинарное)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьВыражениеБинарное Цикл
		Подписка.ПосетитьВыражениеБинарное(ВыражениеБинарное);
	КонецЦикла;
	ДобавитьНаСтек(ВыражениеБинарное);
	ПосетитьВыражениеПоТипу(ВыражениеБинарное.ЛевыйОперанд);
	ПосетитьВыражениеПоТипу(ВыражениеБинарное.ПравыйОперанд);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьВыражениеБинарное Цикл
		Подписка.ПокинутьВыражениеБинарное(ВыражениеБинарное);
	КонецЦикла;
КонецПроцедуры // ПосетитьВыражениеБинарное()

Процедура ПосетитьВыражениеНовый(ВыражениеНовый)
	Перем Выражение, Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьВыражениеНовый Цикл
		Подписка.ПосетитьВыражениеНовый(ВыражениеНовый);
	КонецЦикла;
	ДобавитьНаСтек(ВыражениеНовый);
	Для Каждого Выражение Из ВыражениеНовый.Аргументы Цикл
		Если Выражение <> Неопределено Тогда
			ПосетитьВыражениеПоТипу(Выражение);
		КонецЕсли;
	КонецЦикла;
	Для Каждого Элемент Из ВыражениеНовый.Хвост Цикл
		Если Элемент.Тип = Типы.ВыражениеПоле Тогда
			Если Элемент.Аргументы <> Неопределено Тогда
				Для Каждого Выражение Из Элемент.Аргументы Цикл
					Если Выражение <> Неопределено Тогда
						ПосетитьВыражениеПоТипу(Выражение);
					КонецЕсли;
				КонецЦикла;
			КонецЕсли;
		ИначеЕсли Элемент.Тип = Типы.ВыражениеИндекс Тогда
			ПосетитьВыражениеПоТипу(Элемент.Выражение);
		Иначе
			ВызватьИсключение "нарушение протокола";
		КонецЕсли;
	КонецЦикла;
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьВыражениеНовый Цикл
		Подписка.ПокинутьВыражениеНовый(ВыражениеНовый);
	КонецЦикла;
КонецПроцедуры // ПосетитьВыражениеНовый()

Процедура ПосетитьВыражениеТернарное(ВыражениеТернарное)
	Перем Элемент, Выражение, Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьВыражениеТернарное Цикл
		Подписка.ПосетитьВыражениеТернарное(ВыражениеТернарное);
	КонецЦикла;
	ДобавитьНаСтек(ВыражениеТернарное);
	ПосетитьВыражениеПоТипу(ВыражениеТернарное.Выражение);
	ПосетитьВыражениеПоТипу(ВыражениеТернарное.Тогда);
	ПосетитьВыражениеПоТипу(ВыражениеТернарное.Иначе);
	Для Каждого Элемент Из ВыражениеТернарное.Хвост Цикл
		Если Элемент.Тип = Типы.ВыражениеПоле Тогда
			Если Элемент.Аргументы <> Неопределено Тогда
				Для Каждого Выражение Из Элемент.Аргументы Цикл
					Если Выражение <> Неопределено Тогда
						ПосетитьВыражениеПоТипу(Выражение);
					КонецЕсли;
				КонецЦикла;
			КонецЕсли;
		ИначеЕсли Элемент.Тип = Типы.ВыражениеИндекс Тогда
			ПосетитьВыражениеПоТипу(Элемент.Выражение);
		Иначе
			ВызватьИсключение "нарушение протокола";
		КонецЕсли;
	КонецЦикла;
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьВыражениеТернарное Цикл
		Подписка.ПокинутьВыражениеТернарное(ВыражениеТернарное);
	КонецЦикла;
КонецПроцедуры // ПосетитьВыражениеТернарное()

Процедура ПосетитьВыражениеСкобочное(ВыражениеСкобочное)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьВыражениеСкобочное Цикл
		Подписка.ПосетитьВыражениеСкобочное(ВыражениеСкобочное);
	КонецЦикла;
	ДобавитьНаСтек(ВыражениеСкобочное);
	ПосетитьВыражениеПоТипу(ВыражениеСкобочное.Выражение);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьВыражениеСкобочное Цикл
		Подписка.ПокинутьВыражениеСкобочное(ВыражениеСкобочное);
	КонецЦикла;
КонецПроцедуры // ПосетитьВыражениеСкобочное()

Процедура ПосетитьВыражениеНе(ВыражениеНе)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьВыражениеНе Цикл
		Подписка.ПосетитьВыражениеНе(ВыражениеНе);
	КонецЦикла;
	ДобавитьНаСтек(ВыражениеНе);
	ПосетитьВыражениеПоТипу(ВыражениеНе.Выражение);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьВыражениеНе Цикл
		Подписка.ПокинутьВыражениеНе(ВыражениеНе);
	КонецЦикла;
КонецПроцедуры // ПосетитьВыражениеНе()

Процедура ПосетитьВыражениеСтроковое(ВыражениеСтроковое)
	Перем Выражение, Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьВыражениеСтроковое Цикл
		Подписка.ПосетитьВыражениеСтроковое(ВыражениеСтроковое);
	КонецЦикла;
	ДобавитьНаСтек(ВыражениеСтроковое);
	Для Каждого Выражение Из ВыражениеСтроковое.Элементы Цикл
		ПосетитьВыражениеЛитерал(Выражение);
	КонецЦикла;
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьВыражениеСтроковое Цикл
		Подписка.ПокинутьВыражениеСтроковое(ВыражениеСтроковое);
	КонецЦикла;
КонецПроцедуры // ПосетитьВыражениеСтроковое()

#КонецОбласти // ПосещениеВыражений

#Область ПосещениеОператоров

Процедура ПосетитьОператорПоТипу(Оператор)
	Перем Тип;
	Тип = Оператор.Тип;
	Если Тип = Типы.ОператорПрисваивания Тогда
		ПосетитьОператорПрисваивания(Оператор);
	ИначеЕсли Тип = Типы.ОператорВозврат Тогда
		ПосетитьОператорВозврат(Оператор);
	ИначеЕсли Тип = Типы.ОператорПрервать Тогда
		ПосетитьОператорПрервать(Оператор);
	ИначеЕсли Тип = Типы.ОператорПродолжить Тогда
		ПосетитьОператорПродолжить(Оператор);
	ИначеЕсли Тип = Типы.ОператорВызватьИсключение Тогда
		ПосетитьОператорВызватьИсключение(Оператор);
	ИначеЕсли Тип = Типы.ОператорВыполнить Тогда
		ПосетитьОператорВыполнить(Оператор);
	ИначеЕсли Тип = Типы.ОператорВызоваПроцедуры Тогда
		ПосетитьОператорВызоваПроцедуры(Оператор);
	ИначеЕсли Тип = Типы.ОператорЕсли Тогда
		ПосетитьОператорЕсли(Оператор);
	ИначеЕсли Тип = Типы.ОператорПока Тогда
		ПосетитьОператорПока(Оператор);
	ИначеЕсли Тип = Типы.ОператорДля Тогда
		ПосетитьОператорДля(Оператор);
	ИначеЕсли Тип = Типы.ОператорДляКаждого Тогда
		ПосетитьОператорДляКаждого(Оператор);
	ИначеЕсли Тип = Типы.ОператорПопытка Тогда
		ПосетитьОператорПопытка(Оператор);
	ИначеЕсли Тип = Типы.ОператорПерейти Тогда
		ПосетитьОператорПерейти(Оператор);
	ИначеЕсли Тип = Типы.ОператорМетка Тогда
		ПосетитьОператорМетка(Оператор);
	ИначеЕсли Тип = Типы.ОператорДобавитьОбработчик Тогда
		ПосетитьОператорДобавитьОбработчик(Оператор);
	ИначеЕсли Тип = Типы.ОператорУдалитьОбработчик Тогда
		ПосетитьОператорУдалитьОбработчик(Оператор);
	ИначеЕсли Тип = Типы.ИнструкцияПрепроцессораОбласть
		Или Тип = Типы.ИнструкцияПрепроцессораКонецОбласти
		Или Тип = Типы.ИнструкцияПрепроцессораЕсли
		Или Тип = Типы.ИнструкцияПрепроцессораИначеЕсли
		Или Тип = Типы.ИнструкцияПрепроцессораИначе
		Или Тип = Типы.ИнструкцияПрепроцессораКонецЕсли
		Или Тип = Типы.ИнструкцияПрепроцессораВставка
		Или Тип = Типы.ИнструкцияПрепроцессораКонецВставки
		Или Тип = Типы.ИнструкцияПрепроцессораУдаление
		Или Тип = Типы.ИнструкцияПрепроцессораКонецУдаления Тогда
		ПосетитьИнструкциюПрепроцессора(Оператор);
	КонецЕсли;
КонецПроцедуры // ПосетитьОператорПоТипу()

Процедура ПосетитьОператорПрисваивания(ОператорПрисваивания)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорПрисваивания Цикл
		Подписка.ПосетитьОператорПрисваивания(ОператорПрисваивания);
	КонецЦикла;
	ДобавитьНаСтек(ОператорПрисваивания);
	ПосетитьВыражениеИдентификатор(ОператорПрисваивания.ЛевыйОперанд);
	ПосетитьВыражение(ОператорПрисваивания.ПравыйОперанд);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорПрисваивания Цикл
		Подписка.ПокинутьОператорПрисваивания(ОператорПрисваивания);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорПрисваивания()

Процедура ПосетитьОператорВозврат(ОператорВозврат)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорВозврат Цикл
		Подписка.ПосетитьОператорВозврат(ОператорВозврат);
	КонецЦикла;
	ДобавитьНаСтек(ОператорВозврат);
	Если ОператорВозврат.Выражение <> Неопределено Тогда
		ПосетитьВыражение(ОператорВозврат.Выражение);
	КонецЕсли;
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорВозврат Цикл
		Подписка.ПокинутьОператорВозврат(ОператорВозврат);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорВозврат()

Процедура ПосетитьОператорПрервать(ОператорПрервать)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорПрервать Цикл
		Подписка.ПосетитьОператорПрервать(ОператорПрервать);
	КонецЦикла;
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорПрервать Цикл
		Подписка.ПокинутьОператорПрервать(ОператорПрервать);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорПрервать()

Процедура ПосетитьОператорПродолжить(ОператорПродолжить)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорПродолжить Цикл
		Подписка.ПосетитьОператорПродолжить(ОператорПродолжить);
	КонецЦикла;
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорПродолжить Цикл
		Подписка.ПокинутьОператорПродолжить(ОператорПродолжить);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорПродолжить()

Процедура ПосетитьОператорВызватьИсключение(ОператорВызватьИсключение)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорВызватьИсключение Цикл
		Подписка.ПосетитьОператорВызватьИсключение(ОператорВызватьИсключение);
	КонецЦикла;
	ДобавитьНаСтек(ОператорВызватьИсключение);
	Если ОператорВызватьИсключение.Выражение <> Неопределено Тогда
		ПосетитьВыражение(ОператорВызватьИсключение.Выражение);
	КонецЕсли;
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорВызватьИсключение Цикл
		Подписка.ПокинутьОператорВызватьИсключение(ОператорВызватьИсключение);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорВызватьИсключение()

Процедура ПосетитьОператорВыполнить(ОператорВыполнить)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорВыполнить Цикл
		Подписка.ПосетитьОператорВыполнить(ОператорВыполнить);
	КонецЦикла;
	ДобавитьНаСтек(ОператорВыполнить);
	ПосетитьВыражение(ОператорВыполнить.Выражение);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорВыполнить Цикл
		Подписка.ПокинутьОператорВыполнить(ОператорВыполнить);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорВыполнить()

Процедура ПосетитьОператорВызоваПроцедуры(ОператорВызоваПроцедуры)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорВызоваПроцедуры Цикл
		Подписка.ПосетитьОператорВызоваПроцедуры(ОператорВызоваПроцедуры);
	КонецЦикла;
	ДобавитьНаСтек(ОператорВызоваПроцедуры);
	ПосетитьВыражениеИдентификатор(ОператорВызоваПроцедуры.Идентификатор);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорВызоваПроцедуры Цикл
		Подписка.ПокинутьОператорВызоваПроцедуры(ОператорВызоваПроцедуры);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорВызоваПроцедуры()

Процедура ПосетитьОператорЕсли(ОператорЕсли)
	Перем ОператорИначеЕсли, Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорЕсли Цикл
		Подписка.ПосетитьОператорЕсли(ОператорЕсли);
	КонецЦикла;
	ДобавитьНаСтек(ОператорЕсли);
	ПосетитьВыражение(ОператорЕсли.Выражение);
	ПосетитьОператоры(ОператорЕсли.Тогда);
	Если ОператорЕсли.ИначеЕсли <> Неопределено Тогда
		Для Каждого ОператорИначеЕсли Из ОператорЕсли.ИначеЕсли Цикл
			ПосетитьОператорИначеЕсли(ОператорИначеЕсли);
		КонецЦикла;
	КонецЕсли;
	Если ОператорЕсли.Иначе <> Неопределено Тогда
		ПосетитьОператорИначе(ОператорЕсли.Иначе);
	КонецЕсли;
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорЕсли Цикл
		Подписка.ПокинутьОператорЕсли(ОператорЕсли);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорЕсли()

Процедура ПосетитьОператорИначеЕсли(ОператорИначеЕсли)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорИначеЕсли Цикл
		Подписка.ПосетитьОператорИначеЕсли(ОператорИначеЕсли);
	КонецЦикла;
	ДобавитьНаСтек(ОператорИначеЕсли);
	ПосетитьВыражение(ОператорИначеЕсли.Выражение);
	ПосетитьОператоры(ОператорИначеЕсли.Тогда);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорИначеЕсли Цикл
		Подписка.ПокинутьОператорИначеЕсли(ОператорИначеЕсли);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорИначеЕсли()

Процедура ПосетитьОператорИначе(ОператорИначе)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорИначе Цикл
		Подписка.ПосетитьОператорИначе(ОператорИначе);
	КонецЦикла;
	ДобавитьНаСтек(ОператорИначе);
	ПосетитьОператоры(ОператорИначе.Операторы);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорИначе Цикл
		Подписка.ПокинутьОператорИначе(ОператорИначе);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорИначе()

Процедура ПосетитьОператорПока(ОператорПока)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорПока Цикл
		Подписка.ПосетитьОператорПока(ОператорПока);
	КонецЦикла;
	ДобавитьНаСтек(ОператорПока);
	ПосетитьВыражение(ОператорПока.Выражение);
	ПосетитьОператоры(ОператорПока.Операторы);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорПока Цикл
		Подписка.ПокинутьОператорПока(ОператорПока);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорПока()

Процедура ПосетитьОператорДля(ОператорДля)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорДля Цикл
		Подписка.ПосетитьОператорДля(ОператорДля);
	КонецЦикла;
	ДобавитьНаСтек(ОператорДля);
	ПосетитьВыражениеИдентификатор(ОператорДля.Идентификатор);
	ПосетитьВыражение(ОператорДля.Старт);
	ПосетитьВыражение(ОператорДля.Финиш);
	ПосетитьОператоры(ОператорДля.Операторы);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорДля Цикл
		Подписка.ПокинутьОператорДля(ОператорДля);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорДля()

Процедура ПосетитьОператорДляКаждого(ОператорДляКаждого)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорДляКаждого Цикл
		Подписка.ПосетитьОператорДляКаждого(ОператорДляКаждого);
	КонецЦикла;
	ДобавитьНаСтек(ОператорДляКаждого);
	ПосетитьВыражениеИдентификатор(ОператорДляКаждого.Идентификатор);
	ПосетитьВыражение(ОператорДляКаждого.Коллекция);
	ПосетитьОператоры(ОператорДляКаждого.Операторы);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорДляКаждого Цикл
		Подписка.ПокинутьОператорДляКаждого(ОператорДляКаждого);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорДляКаждого()

Процедура ПосетитьОператорПопытка(ОператорПопытка)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорПопытка Цикл
		Подписка.ПосетитьОператорПопытка(ОператорПопытка);
	КонецЦикла;
	ДобавитьНаСтек(ОператорПопытка);
	ПосетитьОператоры(ОператорПопытка.Попытка);
	ПосетитьОператорИсключение(ОператорПопытка.Исключение);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорПопытка Цикл
		Подписка.ПокинутьОператорПопытка(ОператорПопытка);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорПопытка()

Процедура ПосетитьОператорИсключение(ОператорИсключение)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорИсключение Цикл
		Подписка.ПосетитьОператорИсключение(ОператорИсключение);
	КонецЦикла;
	ДобавитьНаСтек(ОператорИсключение);
	ПосетитьОператоры(ОператорИсключение.Операторы);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорИсключение Цикл
		Подписка.ПокинутьОператорИсключение(ОператорИсключение);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорИсключение()

Процедура ПосетитьОператорПерейти(ОператорПерейти)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорПерейти Цикл
		Подписка.ПосетитьОператорПерейти(ОператорПерейти);
	КонецЦикла;
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорПерейти Цикл
		Подписка.ПокинутьОператорПерейти(ОператорПерейти);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорПерейти()

Процедура ПосетитьОператорМетка(ОператорМетка)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорМетка Цикл
		Подписка.ПосетитьОператорМетка(ОператорМетка);
	КонецЦикла;
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорМетка Цикл
		Подписка.ПокинутьОператорМетка(ОператорМетка);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорМетка()

Процедура ПосетитьОператорДобавитьОбработчик(ОператорДобавитьОбработчик)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорДобавитьОбработчик Цикл
		Подписка.ПосетитьОператорДобавитьОбработчик(ОператорДобавитьОбработчик);
	КонецЦикла;
	ДобавитьНаСтек(ОператорДобавитьОбработчик);
	ПосетитьВыражениеИдентификатор(ОператорДобавитьОбработчик.Событие);
	ПосетитьВыражениеИдентификатор(ОператорДобавитьОбработчик.ОбработчикСобытия);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорДобавитьОбработчик Цикл
		Подписка.ПокинутьОператорДобавитьОбработчик(ОператорДобавитьОбработчик);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорДобавитьОбработчик()

Процедура ПосетитьОператорУдалитьОбработчик(ОператорУдалитьОбработчик)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьОператорУдалитьОбработчик Цикл
		Подписка.ПосетитьОператорУдалитьОбработчик(ОператорУдалитьОбработчик);
	КонецЦикла;
	ДобавитьНаСтек(ОператорУдалитьОбработчик);
	ПосетитьВыражениеИдентификатор(ОператорУдалитьОбработчик.Событие);
	ПосетитьВыражениеИдентификатор(ОператорУдалитьОбработчик.ОбработчикСобытия);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьОператорУдалитьОбработчик Цикл
		Подписка.ПокинутьОператорУдалитьОбработчик(ОператорУдалитьОбработчик);
	КонецЦикла;
КонецПроцедуры // ПосетитьОператорУдалитьОбработчик()

#КонецОбласти // ПосещениеОператоров

#Область ПосещениеВыраженийПрепроцессора

Процедура ПосетитьВыражениеПрепроцессора(ВыражениеПрепроцессора)
	Перем Тип, Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьВыражениеПрепроцессора Цикл
		Подписка.ПосетитьВыражениеПрепроцессора(ВыражениеПрепроцессора);
	КонецЦикла;
	Тип = ВыражениеПрепроцессора.Тип;
	Если Тип = Типы.ВыражениеПрепроцессораСимвол Тогда
		ПосетитьВыражениеПрепроцессораСимвол(ВыражениеПрепроцессора);
	ИначеЕсли Тип = Типы.ВыражениеПрепроцессораБинарное Тогда
		ПосетитьВыражениеПрепроцессораБинарное(ВыражениеПрепроцессора);
	ИначеЕсли Тип = Типы.ВыражениеПрепроцессораНе Тогда
		ПосетитьВыражениеПрепроцессораНе(ВыражениеПрепроцессора);
	ИначеЕсли Тип = Типы.ВыражениеПрепроцессораСкобочное Тогда
		ПосетитьВыражениеПрепроцессораСкобочное(ВыражениеПрепроцессора);
	КонецЕсли;
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьВыражениеПрепроцессора Цикл
		Подписка.ПокинутьВыражениеПрепроцессора(ВыражениеПрепроцессора);
	КонецЦикла;
КонецПроцедуры // ПосетитьВыражениеПрепроцессора()

Процедура ПосетитьВыражениеПрепроцессораСимвол(ВыражениеПрепроцессораСимвол)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьВыражениеПрепроцессораСимвол Цикл
		Подписка.ПосетитьВыражениеПрепроцессораСимвол(ВыражениеПрепроцессораСимвол);
	КонецЦикла;
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьВыражениеПрепроцессораСимвол Цикл
		Подписка.ПокинутьВыражениеПрепроцессораСимвол(ВыражениеПрепроцессораСимвол);
	КонецЦикла;
КонецПроцедуры // ПосетитьВыражениеПрепроцессораСимвол()

Процедура ПосетитьВыражениеПрепроцессораБинарное(ВыражениеПрепроцессораБинарное)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьВыражениеПрепроцессораБинарное Цикл
		Подписка.ПосетитьВыражениеПрепроцессораБинарное(ВыражениеПрепроцессораБинарное);
	КонецЦикла;
	ДобавитьНаСтек(ВыражениеПрепроцессораБинарное);
	ПосетитьВыражениеПрепроцессора(ВыражениеПрепроцессораБинарное.ЛевыйОперанд);
	ПосетитьВыражениеПрепроцессора(ВыражениеПрепроцессораБинарное.ПравыйОперанд);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьВыражениеПрепроцессораБинарное Цикл
		Подписка.ПокинутьВыражениеПрепроцессораБинарное(ВыражениеПрепроцессораБинарное);
	КонецЦикла;
КонецПроцедуры // ПосетитьВыражениеПрепроцессораБинарное()

Процедура ПосетитьВыражениеПрепроцессораНе(ВыражениеПрепроцессораНе)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьВыражениеПрепроцессораНе Цикл
		Подписка.ПосетитьВыражениеПрепроцессораНе(ВыражениеПрепроцессораНе);
	КонецЦикла;
	ДобавитьНаСтек(ВыражениеПрепроцессораНе);
	ПосетитьВыражениеПрепроцессора(ВыражениеПрепроцессораНе.Выражение);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьВыражениеПрепроцессораНе Цикл
		Подписка.ПокинутьВыражениеПрепроцессораНе(ВыражениеПрепроцессораНе);
	КонецЦикла;
КонецПроцедуры // ПосетитьВыражениеПрепроцессораНе()

Процедура ПосетитьВыражениеПрепроцессораСкобочное(ВыражениеПрепроцессораСкобочное)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьВыражениеПрепроцессораСкобочное Цикл
		Подписка.ПосетитьВыражениеПрепроцессораСкобочное(ВыражениеПрепроцессораСкобочное);
	КонецЦикла;
	ДобавитьНаСтек(ВыражениеПрепроцессораСкобочное);
	ПосетитьВыражениеПрепроцессора(ВыражениеПрепроцессораСкобочное.Выражение);
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьВыражениеПрепроцессораСкобочное Цикл
		Подписка.ПокинутьВыражениеПрепроцессораСкобочное(ВыражениеПрепроцессораСкобочное);
	КонецЦикла;
КонецПроцедуры // ПосетитьВыражениеПрепроцессораСкобочное()

Процедура ПосетитьИнструкциюПрепроцессора(ИнструкцияПрепроцессора)
	Перем Подписка;
	Для Каждого Подписка Из Посетитель_Подписки.ПосетитьИнструкциюПрепроцессора Цикл
		Подписка.ПосетитьИнструкциюПрепроцессора(ИнструкцияПрепроцессора);
	КонецЦикла;
	ДобавитьНаСтек(ИнструкцияПрепроцессора);
	Если ИнструкцияПрепроцессора.Владелец().Колонки.Найти("Выражение") <> Неопределено Тогда
		ПосетитьВыражениеПрепроцессора(ИнструкцияПрепроцессора.Выражение);
	КонецЕсли;
	УдалитьСоСтека();
	Для Каждого Подписка Из Посетитель_Подписки.ПокинутьИнструкциюПрепроцессора Цикл
		Подписка.ПокинутьИнструкциюПрепроцессора(ИнструкцияПрепроцессора);
	КонецЦикла;
КонецПроцедуры // ПосетитьИнструкциюПрепроцессора()

#КонецОбласти // ПосещениеВыраженийПрепроцессора

#КонецОбласти // Посетитель

Функция Пуск(Исходник, Знач Плагины, Параметры = Неопределено, Окружение = Неопределено) Экспорт
	Перем Результаты, Плагин;
	Подключить(Плагины);
	Посетить(Разобрать(Исходник, Окружение), Параметры);
	Результаты = Новый Массив;
	Для Каждого Плагин Из Посетитель_Плагины Цикл
		Результаты.Добавить(Плагин.Закрыть());
	КонецЦикла;
	Очистить();
	Возврат Результаты;
КонецФункции // Пуск()

Процедура Очистить() Экспорт
	Парсер_Токены.Очистить();
	Для Каждого Элемент Из Парсер_Узлы Цикл
		Элемент.Значение.ЗаполнитьЗначения(Неопределено);
		Элемент.Значение.Очистить();
	КонецЦикла; 
КонецПроцедуры // Очистить()

Инициализировать();
